这会导致 NSString 泄漏吗?
Does this cause leak of NSString?
我是一名 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 的释放?
非常简短的回答:没有。你不应该释放 scriptText
。 (事实上,你不能。)
在ObjC 手动引用计数中,需要遵循基于方法名的规则。如果您调用名称以 alloc
或 new
开头或包含 copy
的方法,则您有责任在对象上调用 release
或 autorelease
返回给你。此外,如果您在对象上调用 retain
,则您有责任调用 release
或 autorelease
.
根据规则,您调用了 +[NSAppleScript alloc]
,因此您有责任对返回给您的对象调用 release
。您没有调用保留方法来获取 scriptText
;您使用了 NSString 文字 (@"..."
)。所以你不能在上面调用 release
。它不会泄漏。 (如果是,则表示 Apple 代码中存在错误。)
实际工作的方式是 NSString 文字直接存储在二进制文件中,就像在 C 中一样。不需要管理它们,因为它们不直接使用内存。但这与您在手动引用计数下的义务无关。你不应该认为“这是一个字符串文字,所以我不应该对它调用 release
”。那根本不是真的。当规则告诉您调用 release
时,您应该调用 release
。对恰好是文字的值调用 retain
,然后再对其调用 release
是完全正确的。 (这种情况经常发生。您通常不知道您正在使用的 NSString 是否是文字。)
碰巧在 NSString 文字上调用 retain
或 release
什么都不做。他们只是忽略了这个电话。非常短的 NSString 对象甚至不存在于内存中。如果它们足够短,数据将直接存储在指针中(称为“标记指针”)。同样,这只是一个实现细节。你的工作是遵守规则,而不是试图猜测系统。
(带有额外 release
“有效”的不正确代码的原因是文字 NSStrings 忽略了内存管理调用。代码仍然不正确。也没有承诺过度释放对象会导致在任何情况下都会发生崩溃,当它确实发生崩溃时,它是非常非常常见的,因为它发生在一个随机点,远离错误。对象有待处理的 autorelease
调用是很常见的,所以当池排干时你会崩溃,没有提示你的错误在哪里。)
当然,您应该打开 ARC 并让它为您处理。它做得很好。但无论如何,了解规则还是有帮助的。 ARC 使用相同的基于名称的规则来确定放置保留和释放的位置。这就是它可以与手动内存管理无缝互操作的方式。
我是一名 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 的释放?
非常简短的回答:没有。你不应该释放 scriptText
。 (事实上,你不能。)
在ObjC 手动引用计数中,需要遵循基于方法名的规则。如果您调用名称以 alloc
或 new
开头或包含 copy
的方法,则您有责任在对象上调用 release
或 autorelease
返回给你。此外,如果您在对象上调用 retain
,则您有责任调用 release
或 autorelease
.
根据规则,您调用了 +[NSAppleScript alloc]
,因此您有责任对返回给您的对象调用 release
。您没有调用保留方法来获取 scriptText
;您使用了 NSString 文字 (@"..."
)。所以你不能在上面调用 release
。它不会泄漏。 (如果是,则表示 Apple 代码中存在错误。)
实际工作的方式是 NSString 文字直接存储在二进制文件中,就像在 C 中一样。不需要管理它们,因为它们不直接使用内存。但这与您在手动引用计数下的义务无关。你不应该认为“这是一个字符串文字,所以我不应该对它调用 release
”。那根本不是真的。当规则告诉您调用 release
时,您应该调用 release
。对恰好是文字的值调用 retain
,然后再对其调用 release
是完全正确的。 (这种情况经常发生。您通常不知道您正在使用的 NSString 是否是文字。)
碰巧在 NSString 文字上调用 retain
或 release
什么都不做。他们只是忽略了这个电话。非常短的 NSString 对象甚至不存在于内存中。如果它们足够短,数据将直接存储在指针中(称为“标记指针”)。同样,这只是一个实现细节。你的工作是遵守规则,而不是试图猜测系统。
(带有额外 release
“有效”的不正确代码的原因是文字 NSStrings 忽略了内存管理调用。代码仍然不正确。也没有承诺过度释放对象会导致在任何情况下都会发生崩溃,当它确实发生崩溃时,它是非常非常常见的,因为它发生在一个随机点,远离错误。对象有待处理的 autorelease
调用是很常见的,所以当池排干时你会崩溃,没有提示你的错误在哪里。)
当然,您应该打开 ARC 并让它为您处理。它做得很好。但无论如何,了解规则还是有帮助的。 ARC 使用相同的基于名称的规则来确定放置保留和释放的位置。这就是它可以与手动内存管理无缝互操作的方式。