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; }
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With