Objective c 这是否会导致字符串泄漏?

Objective c 这是否会导致字符串泄漏?,objective-c,nsstring,Objective C,Nsstring,我是一名C程序员,但对Objective-C来说是相当陌生的。我已经见过好几次与NSString相关的代码: NSAppleScript* script = [[NSAppleScript alloc] initWithSource: @"<some script code>"]; ... [script release]; 但是上面的代码也运行得很好。这是否意味着[script release]不会自动释放NSObject?换句话说,第一节中的代码是否泄漏了N

我是一名C程序员,但对Objective-C来说是相当陌生的。我已经见过好几次与NSString相关的代码:

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

但是上面的代码也运行得很好。这是否意味着
[script release]
不会自动释放NSObject?换句话说,第一节中的代码是否泄漏了NSString的版本?

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

在ObjC手动引用计数中,需要遵循基于方法名称的规则。如果调用的方法名称以
alloc
new
开头,或包含
copy
,则您负责对返回给您的对象调用
release
autorelease
。此外,如果您对对象调用
retain
,则负责调用
release
autorelease

按照规则,您调用了
+[NSAppleScript alloc]
,因此您负责对返回给您的对象调用
release
。您没有调用保留方法来获取
scriptText
;您使用了NSString文本(
@“…”
)。因此,您不能对其调用
release
。它不漏水。(如果是这样的话,这将表明苹果的代码中有一个bug。)

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

对NSString文本调用
retain
release
没有任何作用。他们只是不理睬电话。非常短的NSString对象甚至不存在于内存中。如果它们足够短,数据将直接存储在指针中(称为“标记指针”)。同样,这只是一个实现细节。你的工作是遵守规则,而不是去猜测系统

(您的错误代码与额外的
版本
有效的原因)这是因为字符串忽略了内存管理调用。代码仍然不正确。也不能保证过度释放对象在任何情况下都会导致崩溃,而且当对象崩溃时,它在远离错误的随机点发生是非常非常常见的。对象具有挂起的
自动释放是非常常见的调用它们,因此当池耗尽时会发生崩溃,而不会提示错误所在。)


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

您应该启用ARC(自动引用计数),它已存在多年,并代表您管理保留/释放。除此之外,字符串文字被视为常量,不受引用计数的影响。如果您可以转换为ARC,这将大大简化您的生活。但是,如果您一直使用手动引用计数,那么Xcode的“静态分析器”(shift+command+B或Xcode的“产品”菜单上的“分析”)非常擅长分析代码以查找手动引用计数问题。确保你从静态分析器那里得到了一份干净的健康清单。你有很多很好的答案,你应该听听。我只想指出,在正常的C语言中,你应该
alloc
free
,并且要非常小心地确保平衡,以防止泄漏。当您打开ARC时,这一切都会自动发生,您不必担心内存泄漏。当然,有时在特殊情况下,您可能会遇到麻烦,但ARC基本上是正确的,如果您正确使用Objective-C(带ARC),那么您就不必担心指针的释放。所以,不要试图用
发布版
取代C的
免费版
,只要打开ARC,开始玩吧。谢谢你对ARC的有用建议,我会打开它的。也许还有助于理解ARC隐藏的潜在机制和隐含规则。我喜欢这个答案谢谢你的回答。详细的回答非常全面地解释了NSString和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];