关于 autorelease/release 和 [pool release]

Posted

技术标签:

【中文标题】关于 autorelease/release 和 [pool release]【英文标题】:About autorelease/release and [pool release] 【发布时间】:2012-04-02 08:14:13 【问题描述】:

这是我的代码:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *string = [[NSString alloc] initWithFormat:@"s"];

[string autorelease];
NSLog(@"retainCount of string is %d", [string retainCount]);

[pool release];
NSLog(@"retainCount of string is %d", [string retainCount]);

当我试图理解自动释放和释放时,我很困惑。 如果使用[string autorelease],在向pool发送release消息后,string的retainCount仍然是1。但是用[string release]替换[string autorelease],最后string的retainCount将为0。我对autorelease的了解是“通过向其发送自动释放消息将对象添加到当前自动释放池以供以后释放”。为什么我向它发送了一条自动释放消息并释放池,我仍然可以访问该对象。

【问题讨论】:

retainCount 永远不能返回零。向释放的对象发送消息会产生未定义的行为。 【参考方案1】:

事情是这样的:retainCount 是一个实现细节。你永远不能依赖它是任何特定的价值。您真正需要考虑的只是您是否拥有一个对象。

分配字符串后,您就拥有了它。当您自动释放字符串时,您不再拥有它,并且在您耗尽/释放自动释放池时它可能会消失。如果没有其他人拥有它,它在您释放自动释放池时消失。无论如何,释放自动释放池后,您无法合法地发送字符串消息。

在当前实现中,创建字符串时保留计数为 1。自动释放不会更改保留计数。当池被释放时,release 被发送到其中的所有对象,包括你的字符串。 release 中的代码如下所示:

if (retainCount == 1)

    [self dealloc];

else

    retainCount--;

因此您可以看到保留计数永远不会降为零。你最终的 NSLog 可以工作,因为字符串使用的内存还没有被回收。

【讨论】:

谢谢你!这有助于我理解 Objective-C 的内存管理。【参考方案2】:

您必须使用 [pool drain] 而不是 release 消息来释放池中所有自动释放的对象。此消息将为您调用 [pool release]

【讨论】:

drain 在引用计数代码中是 release 的同义词。 我试过这个方法。但是在控制台打印的字符串的retainCount仍然是1。 来自NSAutoreleasePool 参考:“当自动释放池被释放时,它会向其所有自动释放的对象发送释放消息” 是的,在向pool发送release消息之前,object的retainCount为1。据此,在[pool release]之后,它向这个object发送release消息,所以它的retainCount为0。它应该被释放。但是我尝试打印它的retainCount,它仍然是1。 @tzzzoz:请参阅我的答案以了解为什么保留计数仍为 1。

以上是关于关于 autorelease/release 和 [pool release]的主要内容,如果未能解决你的问题,请参考以下文章

关于认证和授权

关于go mod 的使用和goland 配置关于go mod 的配置

关于nginx 和 uwsgi

关于在 Google Play 控制台上推出应用程序的问题,包括关于 `aewt` 和 `UID` 和 SDK、API 版本的问题

iptables规则备份和恢复firewall的9个zone关于zone的操作和关于servic

关于 1 和 0.999999……