我在为iPhone模拟器(或设备)编译的Xcode项目中看到的以下行为让我感到困惑:
NSString *test = [[NSString alloc] initWithCString:"foo"];
NSLog(@"test retain count = %d", [test retainCount]); // prints 1
[test release];
NSLog(@"test retain count = %d", [test retainCount]); // also prints 1 instead of 0
然而,任何进一步尝试访问'test'都会导致Xcode环境崩溃,无论是另一个[test retainCount]
NSLog语句还是其他语句(即使只是为了检查test是否等于nil)。 / p>
思考?在一个简单的基于视图的测试项目中编译...代码存在于项目的applicationDidFinishLaunching方法中。
澄清 - 我知道不要在实践中做上述事情。这只是一个测试,看看为什么在某些调试情况下,保留计数为1实际上并不反映对象的实际状态。谢谢你的回复。这只是一个测试存根,看看为什么我在一些情况下看到某些行为。我真正想要做的是追踪每当我销毁/重新创建自定义视图时一直在创建的非常小的内存泄漏(0.06MB)。
答案 0 :(得分:5)
保留计数是一种调试辅助工具,根据Cocoa在幕后可能做的事情可能会产生误导。对于字符串文字尤其如此,其中数据永久可用且永远不会被真正删除。
专注于确保您的代码遵循Cocoa memory management rules对象所有权。必要时,使用Instruments检查实际的内存泄漏。
答案 1 :(得分:5)
在发布并且可能已取消分配后,您在retainCount
上呼叫test
,所以肯定结果不可靠,更不用说您不应该发送解除对象的任何消息。
答案 2 :(得分:0)
不要依赖保留计数......框架可能会保留自己的东西。
相反,依赖于Objective-C的内存管理规则。如果你分配,初始化或新的东西,你拥有它并负责释放它。如果你没有,你就不是。
答案 3 :(得分:0)
不依赖保留计数;相反,请确保平衡保留和释放。以下是Cocoa(Touch)内存管理的一些链接: http://iamleeg.blogspot.com/2008/12/cocoa-memory-management.html
答案 4 :(得分:0)
当你发送release
时,字符串被解除分配 - 它没有其他所有者保留它。向其发送更多消息(包括retainCount
)是一个错误,不会返回任何有意义的消息。
正如其他人所指出的那样,不要依赖保留计数特别有用。它们是你可以看到的一幅画面,但它们往往会产生误导。例如,自动释放不会显示在保留计数中,有时为了缓存目的而保留额外的对象等等。但是,在这种特殊情况下,您根本不会将消息发送到有效对象,所以你'很幸运能找回答案而不是崩溃。
如果你不清楚这些,你应该阅读Apple's memory management guide。它对于编写Cocoa来说并不是太复杂和绝对必要。
答案 5 :(得分:0)
改进上面显示的代码的一个技巧是使用'set to nil'约定。
EG:
NSString * test = [[NSString alloc] initWithCString:“foo”];
NSLog(@“test retain count =%d”,[test retainCount]); //打印1
[测试版]; test =零; //设置为nil,因为我已经释放指针,我不应再使用它了。
NSLog(@“test retain count =%d,test foobarpro =%d”,[test retainCount],[test foobarPro]); //现在将打印0和0 - 因为对nil对象的任何objective-c调用都返回0(并且不会崩溃)
通过在释放之后将指针设置为零,您将来会稍微证明您的代码:稍后出现并编辑下面10行的代码可能会意外地使用“测试”,可能没有任何不良影响(或明显的崩溃)。我甚至在dealloc调用中设置指向nil的指针,因为一些最难的调试任务发生在非破坏的'坏'指针被用于破坏时。
此外,您可以使用僵尸进行调试,以查找使用无效测试等指针的情况。
- 汤姆