Aky*_*Aky 8 objective-c automatic-ref-counting
我正在使用一个简单的命令行应用程序来处理内存(de)分配内容,该应用程序适用于使用启用了ARC的Xcode版本4.2.1构建的Mac OSX 10.7以及默认的构建设置.我无法解释我从ARC的理解中得到的行为,所以我希望有人可以解释这里发生了什么.
首先,在下面的代码中我得到了我期望的行为(请注意NLog()输出在相应语句后的注释中给出)
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSObject *objPtr1 = [[NSObject alloc] init];
NSObject *objPtr2 = objPtr1;
__weak NSObject *weakRef = objPtr1;
NSLog(@"%@", [objPtr1 description]); // <NSObject: 0x1001107d0>
objPtr1 = nil;
NSLog(@"%@", [objPtr2 description]); // <NSObject: 0x1001107d0>
objPtr2 = nil;
NSLog(@"%@", [weakRef description]); // (null)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
所以在上面,在分配了weakRef之后,NSObject实例有两个强指针,因此保留计数为2.在将objPtr1归零后,还有一个保留指向实例的指针,因此它仍然在内存中并响应说明消息.在nir-ing objPtr2之后,没有指向该对象的强指针并且它被解除分配(我假设它是,因为weakRef已被置零).到现在为止还挺好.
现在,相同的代码有一个小的变化:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSObject *objPtr1 = [[NSObject alloc] init];
NSObject *objPtr2 = objPtr1;
__unsafe_unretained NSObject *weakRef = objPtr1; // __unsafe_unretained instead of just __weak
NSLog(@"%@", [objPtr1 description]); // <NSObject: 0x1001107d0>
objPtr1 = nil;
NSLog(@"%@", [objPtr2 description]); // <NSObject: 0x1001107d0>
objPtr2 = nil;
NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>
//why was the object instance not deallocated and the preceding statement not crash the program?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我期待weakRef成为一个悬空指针发送一条消息,通过该消息会导致程序在第三个NSLog()语句中崩溃,但似乎对象实例仍然活着并且很好.
另一件我觉得奇怪的事情:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSObject *objPtr1 = [[NSObject alloc] init];
NSObject *objPtr2 = objPtr1;
__weak NSObject *weakRef = objPtr1; // __weak again
NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>
objPtr1 = nil;
NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>
objPtr2 = nil;
NSLog(@"%@", [weakRef description]); // <NSObject: 0x1001107d0>
return 0;
}
Run Code Online (Sandbox Code Playgroud)
最后一个代码就像第一个代码(使用归零的__weak指针); 唯一的区别是描述消息是在三个NSLog()调用的每一个中通过weakRef发送给对象的.但是这一次,即使在删除了两个强引用之后,对象也没有被释放(因为它仍然通过weakRef响应消息).
那么这里发生了什么?
这看起来确实很奇怪。您对第二位代码的看法是正确的(在您的评论中),因为内存尚未被重新使用。但第三位代码比较奇怪。这是一个更简化的测试用例,显示了这个奇怪的问题:
#import <Foundation/Foundation.h>
@interface SomeClass : NSObject
@end
@implementation SomeClass
- (void)foo {
}
@end
int main (int argc, const char * argv[]) {
@autoreleasepool {
SomeClass *objPtr1 = [[SomeClass alloc] init];
__weak SomeClass *weakRef = objPtr1;
// [weakRef foo];
[weakRef foo];
objPtr1 = nil;
NSLog(@"%p", weakRef);
return 0;
}
}
Run Code Online (Sandbox Code Playgroud)
注释掉该行后,输出为:
$ clang -fobjc-arc -framework Foundation test.m -o test -O3 && ./test
2012-02-12 00:39:42.769 test[6684:707] 0x0
Run Code Online (Sandbox Code Playgroud)
取消注释该行后,输出为:
$ clang -fobjc-arc -framework Foundation test.m -o test -O3 && ./test
2012-02-12 00:42:04.346 test[6688:707] 0x100f13f50
Run Code Online (Sandbox Code Playgroud)
这看起来非常奇怪,对我来说完全就像一个错误。我实际上不知道答案是什么,但我想我会把这个作为答案发布,以便让球滚动起来弄清楚发生了什么。
更新:
如果您在 构建此代码,O0那么似乎只有在没有调用weakRef时才将其归零。一次调用就意味着它不会被归零。foofoo
| 归档时间: |
|
| 查看次数: |
1288 次 |
| 最近记录: |