ARC 是否保证在最后一个强引用消失后立即解除分配对象?



特别是,这类代码是否总是按预期工作(其中MyResourceGuard是一个在其init方法中锁定独占资源并在其dealloc方法中释放锁定的对象):

NSLog(@"About to capture some exclusive resource.");
{
MyResourceGuard* guard = [MyResourceGuard new];
// Do something with the exclusive resource here.
}
// guard is out of scope, therefore its dealloc should have
// been called right away and the resource should already
// be free again at this point.

我在书和博客中读到,与Java垃圾收集相比,ARC在引用计数降至零时立即销毁对象(而不是在自己方便的时候),但我在苹果的任何官方文档中都没有读到这一点。如果这是真的,我们为什么需要在ARC中引入新的@autoreleasepool关键字?

在调试过程中,我总是看到对象立即被解除锁定,除非在try-catch块中引发异常,在这种情况下,解除锁定实际上从未被调用过(这是Mac错误,还是只是Objective C的一个奇怪之处?)。

否。正如您的示例所示,您没有基于确定范围的ObjC对象销毁。

例如,这个程序可能导致死锁:

{ MyResourceGuard* guard = [MyResourceGuard new]; }
{ MyResourceGuard* guard = [MyResourceGuard new]; }

如果需要此功能,最好使用C++类型(SBRM、RAII)——也可以在Objective-C++中使用(但不适用于objc对象)。

它很接近,但您只需要等到引用计数达到零才能调用-dealloc,这就是为什么保证关闭的原因(通常!=总是)。这个问题实际上与为什么您永远不会依赖或使用-retainCount(在它可用的地方)非常相似。示例:自动发布池、异常、对运行时或ARC生成的代码的更改、编译器优化、使用具有不同代码生成标志的实现可能会导致objc对象的寿命超出范围。

更新

clang网站上ARC的整个页面都是关于这个主题的好读物,包括细节、担保(和缺乏担保),但特别是:

6.1.精确的生存期语义

一般来说,ARC保持一个不变量,即一个可保留的对象__strong对象中的指针将保留为完全形式对象的生存期。受此不变量约束的对象具有精确的生存期语义。

默认情况下,自动存储持续时间的本地变量没有精确的生存期语义。这些对象只是强引用保存可保留对象指针类型的值,以及这些值仍然完全受制于local下的值的优化控制

理由:严格应用这些精确的寿命语义禁止的许多理论上可能有用的优化减少对象的寿命将变得不可能。本质上,它承诺的太多了。

可保留对象所有者类型和自动存储的局部变量duration可以用objc_precisie_lifetime属性注释为表明它应该被认为是一个具有精确生存期语义。

理由:尽管如此,有时能够迫使要在精确时间释放的对象,即使该对象没有似乎在使用。这种情况可能非常罕见显式请求这些语义的语法权重将不会繁琐,甚至可能使代码更清晰。

即使使用了objc_precise_lifetime属性,它也将应用于强局部变量的引用计数操作,而不是对象的生存期。

此类代码将始终有效。(或者至少只要ARC像现在这样工作)ARC中对象生命周期的一个小例子:

{
NSString *a = [[NSString alloc] init]; //object allocation
a = nil; // object is deallocated as it was created in this scope
NSString *b = [NSString string]; //method call which returns an object (always autoreleased)
b = nil; // object is not deallocated as it was not created in this scope and is therefore autorelased
}

最新更新