【问题标题】:calling [myString release] does NOT decrement [myString retainCount]调用 [myString release] 不会减少 [myString retainCount]
【发布时间】:2011-03-13 22:06:48
【问题描述】:

我有以下情况,似乎是导致我的 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

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

【问题讨论】:

  • mipadi 可能是对的,但是如果保留计数为 1 并且您在其上调用了 release,那么您已经删除了该对象。因此,retainCount 应该在无效对象上返回任何有用的值是没有意义的。
  • 好的。我将假设概要对象随后被释放。有没有办法确定是否已被释放?

标签: iphone objective-c ipad nsstring


【解决方案1】:

不要依赖RETAINCOUNT

对于人类来说,它不是对象所有权的准确衡量标准。你不知道在框架的幕后调用retainrelease

Cocoa 中的内存管理很简单:

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

【讨论】:

  • 谢谢。我明白,但我试图找出我的应用程序内存不足的原因......我假设我的概要属性由于某种原因没有被释放。 Instruments 在这一点上没有帮助(没有发现泄漏,分配看起来不错,等等)
  • 请把你的第一句话加粗。如果可以的话,增加字体大小。如本例所示,retainCount 作为调试工具绝对没用。
  • 我同意你对retainCount 的反对意见。不过,我认为在这种情况下,最好了解发生了什么以及为什么 retainCount 总是返回一个。
  • @Dave DeLong:我想知道删除retainCount 是否是个好主意。它可能会破坏旧代码,但我怀疑任何严重的代码都使用retainCount(它实际上没用)。
【解决方案2】:

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

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

  1. 现在同一地址上还有其他一些对象,其保留计数为 1。
  2. (更有可能)释放的对象仍然存在。它通过返回保留计数来响应消息,保留计数为 1,因为它从未减为零(永远不需要这样做,因为已释放的对象不需要有效的保留计数)。
  3. 该对象仍然存在并且有一些自定义内存管理,防止 retainCount 被递减。

编辑:

要检查对象的释放(如果您想确定的话),您可以随时覆盖 dealloc 并设置断点或在此处放置日志消息。

【讨论】:

  • 是的,这是有道理的。谢谢。
【解决方案3】:

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

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

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

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

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

• Shark(请参阅 Shark 用户指南)还分析内存分配(在程序的许多其他方面)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 2012-05-23
    • 2017-05-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多