2

我正在运行一些代码,这可能会指出我不太了解堆和堆栈之间的区别。下面我有一些示例代码,我要么在堆栈上声明一个数组,要么在 1234567 个元素的堆上声明一个数组。两者都有效。

int main(int argc, char** argv){

  int N = 1234567;

  int A[N];

  //int* A = new int[N];

}

但是,如果我们将 N 设为 12345678,我会遇到 int A[N] 的段错误,而堆声明仍然可以正常工作。(如果重要的话,我正在使用 g++ O3 -std=c++0x )。这是什么疯狂?堆栈是否有(相当小的)数组大小限制?

4

2 回答 2

6

这是因为堆栈的大小比堆小得多。堆可以占用程序可用的所有内存。默认情况下,VC++ 编译的堆栈大小为 1 MB。该堆栈提供了更好的性能,但适用于更少量的数据。一般来说,它不用于大型数据结构。这就是为什么在 c++ 中接受列表/数组/字典/等的函数通常采用指向该结构的指针或引用。按值传递的参数被复制到堆栈上,传递这样的结构会经常导致程序崩溃。

在您的示例中,您使用的是N int's,anint是 4 个字节。这使得大小A[N]约为 4.7 MB,远大于堆栈的大小。

于 2012-11-29T23:30:58.950 回答
2

堆通过 malloc 和 co 分配动态增长。堆栈随着程序运行过程中的每个函数调用而增长。返回地址、参数、局部变量通常存储在堆栈中(除了在某些处理器架构中,其中少数存储在寄存器中)。也可以(但不常见)动态分配堆栈空间。

堆和栈竞争使用相同的内存。您可以考虑一个从左到右生长,另一个从右到左生长。如果不加以控制,它们可能会发生碰撞。堆栈通常被限制增长超过某个界限。这是相对较小的,因为预计它将只使用几个字节来进行大多数调用,并且只使用几个堆栈级别。限制很小,但对于大多数任务来说已经足够了。您可以通过更改构建设置(但不适用于 Linux ELF 二进制文件)或调用 setrlimit 来扩展此限制。操作系统也可能会施加一个您可以更改的限制。可能有软限制和硬限制(http://www.nics.tennessee.edu/node/327)。

更详细地了解限制超出了问题的范围。底线是堆栈是有限的并且它非常小,因为它与堆竞争实际内存,对于典型的应用程序来说它不需要更大。

http://en.wikipedia.org/wiki/Call_stack

于 2012-11-29T23:31:51.447 回答