Why setting object that is undergoing deallocation to weak property results in crash

Viewed 2193

In Clang's Objective-C Automatic Reference Counting we see the following

For __weak objects, the lvalue is updated to point to the new pointee, unless the new pointee is an object currently undergoing deallocation, in which case the lvalue is updated to a null pointer. This must execute atomically with respect to other assignments to the object, to reads from the object, and to the final release of the new pointee.

In objc-weak.mm wee see the following chunk of code in weak_register_no_lock():

    if (deallocating) {
    if (crashIfDeallocating) {
        _objc_fatal("Cannot form weak reference to instance (%p) of "
                    "class %s. It is possible that this object was "
                    "over-released, or is in the process of deallocation.",
                    (void*)referent, object_getClassName((id)referent));
    } else {
        return nil;
    }
}

I set a breakpoint in my UIViewController subclass dealloc method and tried invoking [self allowsWeakReference] in lldb which resulted in NO value.

If we try to set self to weak property of another object the app will crash in accordance with the objc-weak.mm code.

The question is – why does this happen? Is the clang's specification wrong? Is is this a bug in objc implementation?


Here is a simple piece of code that will reproduce the crash:

//cc -fmodules -fobjc-arc -g crash.m -o crash
@import Foundation;

@interface Foo : NSObject
@end

@implementation Foo
- (void)dealloc {
  Foo * __weak weakSelf = self; // crashes on this line
}
@end

int main() {
  (void)[[Foo alloc] init];
  return 0;
}
1 Answers
Related