Objective-C内存问题(iPhone)

时间:2009-02-26 20:45:03

标签: iphone objective-c memory-management

我在为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)。

6 个答案:

答案 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的指针,因为一些最难的调试任务发生在非破坏的'坏'指针被用于破坏时。

此外,您可以使用僵尸进行调试,以查找使用无效测试等指针的情况。

- 汤姆