我认为我对ARC和选择适当的终身限定符(__strong、__weak、__unsafe_unretained和__autoreleasing)的正确用例有很好的理解。然而,在我的测试中,我发现了一个对我来说没有意义的例子。
据我所知,__weak和__unsafe_unretained都没有添加保留计数。因此,如果没有指向该对象的其他__strong指针,则该对象立即被释放(不可变字符串是此规则的一个例外)。这个过程中唯一的区别是__weak指针被设置为零,而__unsafe_unretained指针被单独保留。
如果我创建一个指向简单的自定义对象的__weak指针(由一个NSString属性组成),则在尝试访问属性时会看到预期的(null)值:
Test * __weak myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: (null)同样,由于所产生的悬空指针,我希望__unsafe_unretained生存期限定符会导致崩溃。但是,在下一个测试中,我看到了实际值:
Test * __unsafe_unretained myTest = [[Test alloc] init];
myTest.myVal = @"Hi!";
NSLog(@"Value: %@", myTest.myVal); // Prints Value: Hi!为什么__unsafe_unretained对象没有被释放?
编辑:对象正在被解除分配.如果我试图用NSLog(@"%@", myTest);替换第2-3行,应用程序就会崩溃(并且在第一行之后将立即调用Test中覆盖的dealloc )。我知道,即使在__unsafe_unretained中,不可变字符串仍然可用,指向NSString的直接指针也能工作。我感到惊讶的是,我可以在一个已释放的对象(第2行)上设置一个属性,并且以后可以从指向它所属的已分配对象的指针中取消它的引用(第3行)!如果有人能解释的话,它肯定会回答我的问题。
发布于 2012-11-21 00:21:44
我感到惊讶的是,我可以在一个已释放的对象(第2行)上设置一个属性,并且以后可以从指向它所属的已分配对象的指针中取消它的引用(第3行)!如果有人能解释的话,它肯定会回答我的问题。
当对象被解除分配时,它不会被归零。由于您有指向已分配对象的指针,并且属性值存储在指向该指针的某个偏移量处,因此在取消分配后存储和检索该属性值是可能的,因此也很有可能由于某种原因所有的东西都会爆炸。
如果您的代码非常脆弱,尝试使用“显示调试过程中的反汇编”进行调试,然后逐步执行,您可能会遇到访问冲突,或者删除Xcode本身.
在C、Objective、C++或任何一个家庭中发生奇怪的事情,您不应该感到惊讶;相反,您应该为很少发生的奇怪事情而感到惊讶!
发布于 2012-11-20 16:57:36
因为objc中的常量字符串是指向堆地址的常量指针,并且该地址仍然有效。
评论后编辑的:
也许是因为测试对象地址上的内存还没有被覆盖,并且仍然包含该对象?推测..。
发布于 2012-11-20 17:11:54
您可以通过实现Test的-dealloc方法和添加一些简单的日志记录来查看何时解除它的分配。
但是,即使测试立即被取消分配,它在RAM中占用的内存在调用myVal时也可能保持不变。
https://stackoverflow.com/questions/13477318
复制相似问题