什么是Swift自动参考计数的自动化?

时间:2016-09-07 20:12:55

标签: swift memory-management automatic-ref-counting reference-counting

是否有某种程序分析在运行时减少/删除引用计数?或者它们只是“自动”,因为程序员不需要手动递增和递减计数,但只要引用/消失就会发生?

基本上,是什么让ARC与正常的引用计数不同?是否有任何已发表的论文讨论正在发生的事情,特别是如果它正在使用程序分析?

2 个答案:

答案 0 :(得分:1)

  

是否有某种程序分析在运行时减少/删除引用计数?

不,正在进行程序分析,以自动插入维持引用计数的调用。

  

或者它们只是“自动”,因为程序员不需要手动递增和递减计数......

完全。在ARC之前,Objective-C程序员必须小心地在对象上调用-retain时要保持对它的引用,并在-release完成对象的引用时。这些方法递增和递减对象的引用计数。使用ARC,编译器会确定应该添加这些调用的位置并插入它们(或等效代码)。因此,从程序员的角度来看,引用计数是自动的。

答案 1 :(得分:1)

自动引用计数(ARC)在编译时涉及静态分析,但执行任何运行时分析。

概念化ARC的简单方法是两遍过程。首先,它检查您的代码并在引入对象引用和/或超出范围的位置插入内存管理代码(在语义上等同于ARC ObjC之前的retainrelease调用)。所以这个:

func doSomething() -> Object {
    let thing1 = Object(name: "foo")
    var thing2 = Object(name: "bar")
    thing2 = Object(name: "baz")
    return thing2
}

...变成(在某些编译器内部中间形式中)这样的东西:

func doSomething() -> Object {
    let thing1 = Object(name: "foo")
    __retain(thing1) // increment reference count so thing1 sticks around

    var thing2 = Object(name: "bar")
    __retain(thing2) // increment reference count so thing2 sticks around

    let oldThing2 = thing2 // thing2 gets replaced on the next line
    thing2 = Object(name: "baz")
    __release(oldThing2) // get rid of the thing that got overwritten
    __retain(thing2) // hold onto the new thing that replaced it

    __release(thing1) // end of scope, so nothing else will use thing1
    return __autorelease(thing2) // relinquish ownership of thing2,
        // but only upon handing ownership over to our caller
}

引入对象引用的时间以及它们超出范围或被传递给调用者的时间(通过return语句)是从一行到另一行完成程序语义的最低要求,但是停止在此分析级别导致冗余内存管理。 (例如,thing1在创建之后永远不会被使用。所以ARC做的下一件事就是流量分析以消除冗余并执行其他优化,使我们的示例伪代码更像是这样:

func doSomething() -> Object {
    _ = Object(name: "foo") // formerly thing1
    // Object.init(name:) is called in case it has side effects, 
    // but the result is immediately discarded because it's not used

    _ = Object(name: "bar") // formerly thing2
    // again we call the initializer but discard the result,
    // because the original thing2 is immediately overwritten

    let thing2 = Object(name: "baz")
    // no retain, because nothing happens between here and return
    // that could affect the memory lifetime of thing2

    return __magic_autorelease(thing2) 
    // and there's other voodoo we can do to ensure handoff to the caller
    // without getting into retain count tracking or autorelease pools
}

这显然是一个非常随意的概述 - 在幕后有更多的内容,所以真正的实现并不完全适合这个简单的两步过程,但从概念上来说它非常相似。有关更详细的讨论,请查看:

前两个是关于Objective-C中的ARC,但是Swift中的ARC是非常密切相关的,所以如果你想知道ARC是如何工作的,最好看看它的ObjC起源。