I noticed the following in Objective-C with ARC enabled:
我在Objective-C中注意到以下内容并启用了ARC:
Let's have simple class A and autosynthesized weak property
让我们有简单的A类和自动合成的弱属性
@interface A
@property (nonatomic, weak) id refObject;
@end
@implementation A
@end
And second class B with dealloc implemented
并且实现了dealloc的第二类B.
@interface B
@end
@implementation B
-(void) dealloc
{
NSLog(@"In dealloc");
}
@end
And finally somewhere in class A have the following:
最后,A类的某个地方有以下几点:
@implementation A
...
-(void) foo
{
B* b = [B new];
self.refObject = b;
// Just use b after the weak assignment
// in order to not dealloc 'b' before assignement
NSLog(@"%@", b);
}
...
@end
If I set a breakpoint in [B dealloc]
and inspect [A refObject]
property I can see that a.refObject
is nil but a->_refObject
is not nil and points to 'b'
如果我在[B dealloc]中设置断点并检查[A refObject]属性,我可以看到a.refObject是nil但是 - > _ refObject不是nil并且指向'b'
Any ideas why that happens?
任何想法为什么会发生?
1 个解决方案
#1
23
Short answer: The instance variable a->_refObject
is not (yet) nil in -[B dealloc]
, but each access to that weak pointer is done through a ARC runtime function that returns nil if the deallocation has already begun.
简短回答:实例变量a - > _ refObject在([B dealloc]中)还没有(但是)nil,但是对该弱指针的每次访问都是通过ARC运行时函数完成的,如果解除分配已经开始,则返回nil。
Long answer: By setting a watchpoint you can see that a->_refObject
is set to nil at the end of the deallocation process. The stack backtrace (when the watchpoint is hit) looks like this:
答案很长:通过设置观察点,您可以看到在重新分配过程结束时将 - > _ refObject设置为nil。堆栈回溯(当观察点被击中时)如下所示:
frame #0: 0x00007fff8ab9f0f8 libobjc.A.dylib`arr_clear_deallocating + 83
frame #1: 0x00007fff8ab889ee libobjc.A.dylib`objc_clear_deallocating + 151
frame #2: 0x00007fff8ab88940 libobjc.A.dylib`objc_destructInstance + 121
frame #3: 0x00007fff8ab88fa0 libobjc.A.dylib`object_dispose + 22
frame #4: 0x0000000100000b27 weakdealloc`-[B dealloc](self=0x000000010010a640, _cmd=0x00007fff887f807b) + 151 at main.m:28
frame #5: 0x0000000100000bbc weakdealloc`-[A foo](self=0x0000000100108290, _cmd=0x0000000100000e6f) + 140 at main.m:41
frame #6: 0x0000000100000cf5 weakdealloc`main(argc=1, argv=0x00007fff5fbff968) + 117 at main.m:52
frame #7: 0x00007fff8c0987e1 libdyld.dylib`start + 1
and object_dispose()
is called from -[NSObject dealloc]
(as can be seen in http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm).
和 - [NSObject dealloc]调用object_dispose()(可以在http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm中看到)。
Therefore in -[B dealloc]
, a->_refObject
is not nil before the (compiler generated) [super dealloc]
is called.
因此在 - [B dealloc]中,a - > _ refObject在调用(编译器生成的)[super dealloc]之前不是nil。
So the question remains: Why does a.refObject
return nil at that point?
所以问题仍然存在:为什么a.refObject在那时返回nil?
The reason is that for each access to a weak pointer the ARC compiler generates a call to objc_loadWeak()
or objc_loadWeakRetained()
. From the documentation:
原因是,对于每次访问弱指针,ARC编译器都会生成对objc_loadWeak()或objc_loadWeakRetained()的调用。从文档:
id objc_loadWeakRetained(id *object)
id objc_loadWeakRetained(id * object)
If object is registered as a __weak object, and the last value stored into object has not > yet been deallocated or begun deallocation, retains that value and returns it. Otherwise > returns null.
如果object被注册为__weak对象,并且存储到object中的最后一个值尚未被释放或开始取消分配,则保留该值并返回该值。否则>返回null。
So even if a->refObject
is not nil at that point, accessing the weak pointer via objc_loadWeakRetained()
(as done by the property accessor method) returns nil, because the deallocation of the B
object has already begun.
因此,即使a-> refObject在该点不是nil,通过objc_loadWeakRetained()访问弱指针(由属性访问器方法完成)也会返回nil,因为B对象的释放已经开始。
The debugger accesses a->refObject
directly and does not call objc_loadWeak()
.
调试器直接访问a-> refObject,不调用objc_loadWeak()。
#1
23
Short answer: The instance variable a->_refObject
is not (yet) nil in -[B dealloc]
, but each access to that weak pointer is done through a ARC runtime function that returns nil if the deallocation has already begun.
简短回答:实例变量a - > _ refObject在([B dealloc]中)还没有(但是)nil,但是对该弱指针的每次访问都是通过ARC运行时函数完成的,如果解除分配已经开始,则返回nil。
Long answer: By setting a watchpoint you can see that a->_refObject
is set to nil at the end of the deallocation process. The stack backtrace (when the watchpoint is hit) looks like this:
答案很长:通过设置观察点,您可以看到在重新分配过程结束时将 - > _ refObject设置为nil。堆栈回溯(当观察点被击中时)如下所示:
frame #0: 0x00007fff8ab9f0f8 libobjc.A.dylib`arr_clear_deallocating + 83
frame #1: 0x00007fff8ab889ee libobjc.A.dylib`objc_clear_deallocating + 151
frame #2: 0x00007fff8ab88940 libobjc.A.dylib`objc_destructInstance + 121
frame #3: 0x00007fff8ab88fa0 libobjc.A.dylib`object_dispose + 22
frame #4: 0x0000000100000b27 weakdealloc`-[B dealloc](self=0x000000010010a640, _cmd=0x00007fff887f807b) + 151 at main.m:28
frame #5: 0x0000000100000bbc weakdealloc`-[A foo](self=0x0000000100108290, _cmd=0x0000000100000e6f) + 140 at main.m:41
frame #6: 0x0000000100000cf5 weakdealloc`main(argc=1, argv=0x00007fff5fbff968) + 117 at main.m:52
frame #7: 0x00007fff8c0987e1 libdyld.dylib`start + 1
and object_dispose()
is called from -[NSObject dealloc]
(as can be seen in http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm).
和 - [NSObject dealloc]调用object_dispose()(可以在http://www.opensource.apple.com/source/objc4/objc4-532/runtime/NSObject.mm中看到)。
Therefore in -[B dealloc]
, a->_refObject
is not nil before the (compiler generated) [super dealloc]
is called.
因此在 - [B dealloc]中,a - > _ refObject在调用(编译器生成的)[super dealloc]之前不是nil。
So the question remains: Why does a.refObject
return nil at that point?
所以问题仍然存在:为什么a.refObject在那时返回nil?
The reason is that for each access to a weak pointer the ARC compiler generates a call to objc_loadWeak()
or objc_loadWeakRetained()
. From the documentation:
原因是,对于每次访问弱指针,ARC编译器都会生成对objc_loadWeak()或objc_loadWeakRetained()的调用。从文档:
id objc_loadWeakRetained(id *object)
id objc_loadWeakRetained(id * object)
If object is registered as a __weak object, and the last value stored into object has not > yet been deallocated or begun deallocation, retains that value and returns it. Otherwise > returns null.
如果object被注册为__weak对象,并且存储到object中的最后一个值尚未被释放或开始取消分配,则保留该值并返回该值。否则>返回null。
So even if a->refObject
is not nil at that point, accessing the weak pointer via objc_loadWeakRetained()
(as done by the property accessor method) returns nil, because the deallocation of the B
object has already begun.
因此,即使a-> refObject在该点不是nil,通过objc_loadWeakRetained()访问弱指针(由属性访问器方法完成)也会返回nil,因为B对象的释放已经开始。
The debugger accesses a->refObject
directly and does not call objc_loadWeak()
.
调试器直接访问a-> refObject,不调用objc_loadWeak()。