Go怎么没有stackoverflows

时间:2010-11-19 16:18:07

标签: memory-management stack language-design stack-overflow go

我在此演示文稿http://golang.org/doc/ExpressivenessOfGo.pdf中读到了第42页:

  

安全

     

- 没有堆栈溢出

这怎么可能?和/或Go如何避免这种情况?

5 个答案:

答案 0 :(得分:16)

这是一个名为“分段堆栈”的功能:每个goroutine都有自己的堆栈allocated on the heap

在最简单的情况下,编程语言实现每个进程/地址空间使用一个堆栈,通常使用称为pushpop的特殊处理器指令(或类似的东西)进行管理,并实现为动态从固定地址开始的堆栈帧数组(通常是虚拟内存的顶部)。

那是(或曾经)快,但不是特别安全。当大量代码在同一地址空间(线程)中并发执行时,会导致麻烦。现在每个人都需要自己的堆栈。但是,所有堆栈(除了一个堆栈)必须是固定大小的,以免它们彼此重叠或与堆重叠。

但是,任何使用堆栈的编程语言也可以通过以不同方式管理堆栈来实现:通过使用保存堆栈帧的列表数据结构或类似物,但实际上是在堆上分配的。堆填满之前没有堆栈溢出。

答案 1 :(得分:5)

它使用分段堆栈。这基本上意味着它使用链表而不是固定大小的数组作为它的堆栈。当它用完空间时,它会使堆栈变大一些。

编辑:

以下是一些更多信息:http://golang.org/doc/go_faq.html#goroutines

这是如此之大的原因并不是因为它永远不会溢出(这是一个很好的副作用),而是你可以用非常小的内存占用创建线程,这意味着你可以有很多它们。

答案 2 :(得分:2)

我认为他们不能“完全”避免堆栈溢出。它们提供了一种方法来防止最典型的与编程相关的错误产生堆栈溢出。

当内存完成时,无法防止堆栈溢出。

答案 3 :(得分:0)

即使是C也可以通过一些基本上影响编译器的约束来实现。

这是一项令人印象深刻的工程壮举,但不是语言设计。

答案 4 :(得分:0)

我认为他们在这里指的是始终根据数组的实际长度检查对数组的访问,从而禁用C程序意外崩溃或恶意崩溃的最常见方式之一。

例如:

package main

func main() {
    var a [10]int

    for i:= 0; i < 100; i++ {
        a[i] = i
    }
}

panic尝试更新数组中不存在的第11个元素时会发生运行时错误。 C会在堆上涂鸦,也可能会以不受控制的方式崩溃。每个阵列都知道它的长度。在某些情况下,如果可以证明它们不是必需的,编译器可以优化检查。 (或者一个足够聪明的编译器也许可以静态地检测到这个函数中的问题。)

许多其他答案都在谈论堆栈的内存布局,但这实际上并不相关:你也可能有堆溢出攻击。

除非你专门使用unsafe包,否则基本上Go的指针应始终是类型安全的,包括数组和其他类型。