1

对于以下

NSImage *image = [[UIImage imageNamed:@"foo.png"] retain];
...
[image release];

我的理解是,从 imageNamed 返回的对象应该会被自动释放。但是由于对象上有一个保留,然后是一个明确的释放。显式释放不仅会减少引用计数,还会触发整个对象的释放,而不是等待稍后进行 GC。假设是,当释放调用时,iOS 将首先尝试减少对象上的引用计数,然后发现当时没有其他主体在引用该对象,因此它决定释放分配的内存。是正确的理解和假设吗?

4

3 回答 3

2

不,这是不正确的。

此外,您对内存管理术语有些松懈,因此您的问题有点令人困惑。

对所有这些方面的详细讨论对于 SO 帖子来说太多了。

自动释放池不是垃圾收集。将其视为对象的集合。当您自动释放对象时,该对象将添加到池中。当池耗尽时,它基本上对池中的每个对象调用释放(因此,名称为自动释放池)。

因此,如果您有一个已自动释放的对象,并且您进行了额外的retain调用(没有匹配的释放),则自动释放池将不会释放该对象。它只会像预期的那样释放一次。

如果您持有对该对象的其他引用,则该对象仍将存在于自动释放池之后。

多次调用保留/释放只是增加和减少计数。在计数达到零之前,对象不会释放。

于 2012-09-10T16:31:27.133 回答
1

这不是一个正确的假设。将release在概念上否定retain. 但是,您无法知道任何其他可能浮动的引用计数。如果retain是唯一的,那么它将立即被摧毁。当然不是这样。

因为我们知道我们得到了一个自动释放的对象,我们知道我们的retain引用不是唯一的。来自自动释放源的原始引用将保留,直到当前自动释放池被耗尽。因此,您的假设在这里是有缺陷的:

当释放调用时,iOS 会首先尝试减少对象的引用计数,然后发现当时没有其他主体在引用该对象,因此决定释放分配的内存。

...因为原始自动释放的引用将保留。

一般来说,您不应该对对象何时被解除分配做出任何假设。只需担心平衡您自己的保留数量并相信事情会解决。在此示例中,存在的引用也可能远不止您自己的retain和假定的autorelease. 只要事情保持平衡,框架就可以在幕后自由保留和释放他们想要的一切。

最后,只需使用 ARC 并忘记这一切 :)

于 2012-09-10T16:30:06.693 回答
1

没有这样的垃圾收集。严格来说,它是对自己的引用进行计数的对象。当一个对象被创建时,它给自己一个引用计数 1。不过,在这种情况下,创建对象的方法 -- imageNamed:-- 将对象放入一个自动释放池中。这意味着池是 1 引用的所有者,它会在以后自动释放引用(在此方法完成后)。

当一个对象的引用计数下降到 0 时,它会通过运行它的dealloc方法来销毁自己。

您发送retain到图像(由自动释放池拥有)意味着有另一个引用 - 另一个所有者 - (然后计数将是 2,但您真的不应该考虑对象的内部绝对数,只考虑您的所有权)。

无论如何,池仍然会发送release,但是(如果您尚未释放通过发送获得的所有权声明retain),此释放本身不会将引用计数降至 0,因此对象不会被销毁。

既然你发送release了,你就放弃了你的声明,自动释放池将处理它的所有权——但更,当你发送时不正确release——导致图像被破坏。

简而言之,不,您的发送release不会改变自动释放池的操作。它仍然拥有该对象,并且仍然release在运行循环结束时发送给它。

于 2012-09-10T16:40:50.030 回答