【问题标题】:Does this cause leak of NSString?这会导致 NSString 泄漏吗?
【发布时间】:2021-04-10 11:28:49
【问题描述】:

我是一名 C 程序员,但对 Objective-C 很陌生。类似这样的 NSString 相关代码我已经看过好几次了:

NSAppleScript* script = [[NSAppleScript alloc] initWithSource: @"<some script code>"];
...
[script release];

上面的代码显式释放了 NSAppleScript 对象,但似乎没有在任何地方释放 NSString 对象。

我想知道[script release]是否会自动完成 NSString 对象的隐式释放工作,所以我将上面的代码更改为:

NSString* scriptText = @"<some script code>";
NSAppleScript* script = [[NSAppleScript alloc] initWithSource: scriptText];
...
[script release];
//If [script release] has implicitly released scriptText,
//this would cause a repeated release.
[scriptText release];

但上面的代码运行起来也很好。这是否意味着[script release] 不会自动释放 NSObject 对象?也就是说,第一节的代码是不是泄露了NSString的释放?

【问题讨论】:

  • 您应该启用已存在多年并代表您管理保留/释放的 ARC(自动引用计数)。除此之外,字符串文字被视为常量,不受引用计数的影响。
  • 如果您可以过渡到 ARC,那将大大简化您的生活。但是,如果您坚持使用手动引用计数,Xcode 的“静态分析器”(shift+command+B 或 Xcode 的“产品”菜单上的“分析”)非常擅长分析代码以查找手动引用计数问题。确保从静态分析器中获得干净的健康状况。
  • 你有很多很棒的答案,你应该听一听。我只想指出,在正常的 C 语言中,你会使用 allocfree 并非常小心地确保平衡它以防止泄漏。当您打开 ARC 时,这一切都会自动发生,您不必担心内存泄漏。当然,有时在特殊情况下您可能会遇到麻烦,但 ARC 大多是正确的,如果您正确使用 Objective-C(与 ARC),那么您不必担心指针的释放。所以不要试图用release代替C的free,只要打开ARC就可以开始玩了。
  • 感谢您对 ARC 的有益建议,我会开启它。无论如何也可能有助于理解 ARC 隐藏的底层机制和隐含规则。

标签: objective-c nsstring


【解决方案1】:

非常简短的回答:不。你不应该释放scriptText。 (事实上​​,你不能这样做。)

在 ObjC 手动引用计数中,您需要遵循规则,这些规则是基于方法名称的。如果您调用名称以allocnew 开头或包含copy 的方法,则您有责任在返回给您的对象上调用releaseautorelease。另外,如果你在一个对象上调用retain,你有责任调用releaseautorelease

按照规则,您调用了+[NSAppleScript alloc],因此您有责任在返回给您的对象上调用release。你没有调用保留方法来获取scriptText;您使用了 NSString 文字 (@"...")。所以你不能打电话给release。它不会泄漏。 (如果确实如此,则表明 Apple 代码中存在错误。)

实际工作的方式是 NSString 文字直接存储在二进制文件中,就像在 C 中一样。不需要管理它们,因为它们不直接使用内存。但这与您在手动引用计数下的义务无关。你不应该认为“这是一个字符串文字,所以我不应该在上面调用release。”这根本不是真的。当规则告诉您拨打release 时,您应该拨打release。对碰巧是文字的值调用 retain 是完全正确的,然后再对它调用 release。 (这种情况经常发生。您通常不知道您正在使用的 NSString 是否是文字。)

在 NSString 字面量上调用 retainrelease 碰巧没有任何作用。他们只是忽略了电话。非常短的 NSString 对象甚至不存在于内存中。如果它们足够短,则数据直接存储在指针中(称为“标记指针”)。同样,这只是一个实现细节。你的工作是遵守规则,而不是猜测系统。

(您的错误代码带有额外的release“有效”的原因是因为文字 NSStrings 忽略了内存管理调用。代码仍然不正确。也没有保证过度释放对象会导致任何崩溃情况下,当它在随机点发生崩溃时,它是非常非常常见的,远离错误。对于对象来说,有待处理的autorelease调用它们是很常见的,所以当池排水,没有提示您的错误在哪里。)

当然,您应该打开 ARC 并让它为您处理。它做得很好。但无论如何,理解规则是有帮助的。 ARC 使用相同的基于名称的规则来确定在何处放置保留和释放。这就是它可以与手动内存管理无缝互操作的方式。

【讨论】:

  • 我喜欢这个答案
  • 感谢您的出色回答。详细的回答非常全面地解释了关于 NSString 和 NSString 字面量的概念和机制。
猜你喜欢
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多