在Swift中递归调用期间的BAD_ACCESS

Tom*_*Tom 6 recursion swift

在玩Swift时,我遇到了崩溃的情况,我仍然没有弄明白为什么.

我们来定义:

class TestClass {

    var iteration: Int = 0

    func tick() -> Void{
        if iteration > 100000 {
            print("Done!")
            return
        }
        iteration++
        tick()
    }
}
Run Code Online (Sandbox Code Playgroud)

tick()函数调用自身并且每次递增iteration.任何类型的电话

let test = TestClass()
test.tick()
Run Code Online (Sandbox Code Playgroud)

在相当少的递归(我的iMac上大约50000)之后程序崩溃,并出现EXC_BAD_ACCESS错误:EXC_BAD_ACCESS

如果我定义一个类似struct而不是a class,则没有崩溃(至少不在这些限制内).请注意,当它崩溃时,程序只使用几MB的RAM.

我无法解释为什么会崩溃.有人有解释吗?这个callbackStorage值似乎很可疑,但我没有找到任何指针.

dan*_*itz 7

您在这里遇到的运行时错误是堆栈溢出。您在修改定义以使用结构体时没有遇到它的事实并不意味着它不会发生。稍微增加迭代深度,您还可以使用结构实现实现相同的运行时错误。由于隐式参数被传递,它会在类实现中更快地达到这一点。


Nob*_*ica 7

在你的程序中,每个线程都有一个称为堆栈的东西.堆栈是一个LIFO(后进先出) - 一个有两个主要操作的数据容器:push,它将一个元素添加到堆栈顶部,pop,它从堆栈顶部删除一个项目.

当你的程序调用一个函数时,它会调用调用该函数的代码的位置,称为返回地址(有时也是某些函数的参数),然后跳转到该函数的代码.(函数的局部变量也存储在堆栈中.)当函数返回时,它会弹出堆栈的返回地址并跳转到它.

但是,堆栈的大小有限.在您的示例中,您的函数调用自身很多次,以至于堆栈中没有足够的空间用于所有返回地址,参数和局部变量.这称为堆栈溢出(这是该网站的名称来源).该程序试图写栈的结束,导致段错误.

正如dans3itz所说,当你使用a时程序没有崩溃的原因struct很可能是因为类比结构有更多的开销.