调用[myString release]不会减少[myString retainCount]

时间:2010-07-09 14:37:37

标签: iphone objective-c ipad nsstring

我有以下情况,这似乎导致我的iPad应用程序泄漏内存。

我有一个带字符串属性的类......

@property(nonatomic,retain) NSString * synopsis;

我从一些HTTP响应设置字符串属性,来自JSON或XML响应。

此时,概要对象的保留计数为1.

但我有这种情况:

我将概要保存到本地sqlite数据库,然后我想从内存中释放它,但我有一种奇怪的情况,从我的对象中调用[synopsis release]不会将保留计数减少到0。

(void) save
{
  NSLog(@"synopsis before save retainCount=%d",[synopsis retainCount]);
  [self saveToDb:synopsis withKey:@"synopsis"];
  NSLog(@"synopsis after save retainCount=%d",[synopsis retainCount]);
  [synopsis release];
  NSLog(@"synopsis after release retainCount=%d",[synopsis retainCount]);
  synopsis=nil;
}

在控制台中我得到:

synopsis before save retainCount=1

synopsis after save retainCount=1

synopsis after release retainCount=1

这怎么可能?我在模拟器或设备上运行相同的结果。

3 个答案:

答案 0 :(得分:10)

不要依赖RETAINCOUNT

对于人类来说,它不是对象所有权的准确度量。您不知道框架中幕后的retainrelease是什么。

Cocoa中的内存管理很简单:

  1. 如果您alloc / initcopy是某个对象,请务必在某个时刻致电release
  2. 如果您想保留一个对象,请致电retain - 但请务必在某个时候致电release

答案 1 :(得分:1)

您的第三个NSLog可能会在已释放的对象上调用retainCount

事实上,您看到值为1可能有三个原因:

  1. 现在在同一地址有一些其他对象,其保留计数为一。
  2. (更有可能)解除分配的对象仍在那里。它通过返回保留计数来响应消息,因为它永远不会减少到零(因为释放的对象不需要有效的保留计数,所以不需要这样做)。
  3. 该对象仍然存在,并且有一些自定义内存管理,阻止retainCount递减。
  4. 修改

    要检查对象的释放(如果您想确定),可以始终覆盖dealloc并设置断点或在其中放置日志消息。

答案 2 :(得分:1)

这可能会有所帮助。来自关于retainCount的文档:

重要说明:此方法在调试内存管理问题时通常没有价值。因为任何数量的框架对象可能保留了一个对象以保存对它的引用,而同时自动释放池可能在对象上保留任意数量的延迟版本,所以您不太可能从此获取有用信息方法

要了解您必须遵守的内存管理的基本规则,请阅读“内存管理规则”。要诊断内存管理问题,请使用合适的工具:

•LLVM / Clang Static分析器通常可以在运行程序之前发现内存管理问题。

•Instruments应用程序中的Object Alloc仪器(参见仪器用户指南)可以跟踪对象分配和销毁。

•Shark(参见Shark用户指南)还会描述内存分配(在程序的许多其他方面)。