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

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.

  • Frontmost UIView with TapGestureRecognizer not receiving touches
  • C++11 standard libraries in libstdc++ on Mac
  • Compiling Assembly (.S) file alongside iPhone project
  • How to enable ARC for a single file
  • Automatic Reference Counting Issue: Passing address of non-local object to __autoreleasing parameter for write-back
  • how to use delegates with Automatic Reference Counting
  • 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;
    }
    

    Solutions Collect From Internet About “Why setting object that is undergoing deallocation to weak property results in crash”

    It’s not a bug: it’s obviously very intentional. It is a deviation from the spec, but it’s an intentional one.

    Based on the warning, it sounds like they wanted to make it easier to diagnose over-release scenarios, and catching objects that are being deallocated at the time might just be a side effect of that main goal.

    They might also consider that, if you’re trying to weakify self while being deallocated anyway, and you’re not checking for a nil weakref (quite common – lots of block code repeatedly calls through a weakref that could go nil at any time!), you’re setting yourself up for hard to debug bugs.

    All that said, I’d love to see the notes behind that runtime change.