代码之家  ›  专栏  ›  技术社区  ›  OscarRyz

为什么Go没有stackoverflows

  •  20
  • OscarRyz  · 技术社区  · 15 年前

    我在报告中看到了 http://golang.org/doc/ExpressivenessOfGo.pdf 第42页:

    保险柜

    -无堆栈溢出

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

    5 回复  |  直到 15 年前
        1
  •  16
  •   Fred Foo    15 年前

    allocated on the heap .

    在最简单的情况下,编程语言实现使用每个进程/地址空间的一个堆栈,通常由名为 push pop (或类似的)并实现为从固定地址(通常是虚拟内存的顶部)开始的堆栈帧的动态数组。

    这是(或过去是)快,但不是特别安全。当大量代码在同一地址空间(线程)中并发执行时,它会导致问题。现在每个都需要自己的堆栈。但是,所有堆栈(可能只有一个)必须是固定大小的,以免它们彼此重叠或与堆重叠。

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

        2
  •  5
  •   dan_waterworth    15 年前

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

    编辑:

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

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

        3
  •  2
  •   fabmilo    15 年前

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

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

        4
  •  0
  •   Joshua    15 年前

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

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

        5
  •  0
  •   poolie    15 年前

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

    例如:

    package main
    
    func main() {
        var a [10]int
    
        for i:= 0; i < 100; i++ {
            a[i] = i
        }
    }
    

    panic 当它试图更新数组中不存在的第十一个元素时,会出现运行时错误。C会在堆上乱涂乱画,可能还会崩溃,但不受控制。每个数组都知道它的长度。在某些情况下,如果编译器能够证明这些检查是不必要的,那么编译器就可以优化这些检查。(或者一个足够聪明的编译器也许可以静态地检测这个函数中的问题。)

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

    基本上Go的指针应该始终是类型安全的,包括数组和其他类型,除非您特别使用 unsafe 包裹。