我正在运行一些代码,可能指出我不太了解堆和堆栈之间的区别。下面我有一些示例代码,我在堆栈或1234567元素的堆上声明一个数组。两者都有效。
int main(int argc, char** argv){
int N = 1234567;
int A[N];
//int* A = new int[N];
}
但是如果我们将N设为12345678,我会得到一个带有int A [N]的seg错误,而堆声明仍然可以正常工作。 (如果重要的话,我正在使用g ++ O3 -std = c ++ 0x)。这有什么疯狂的?堆栈是否有(相当小的)数组大小限制?
答案 0 :(得分:6)
这是因为堆栈的大小比堆小得多。堆可以占用程序可用的所有内存。默认情况下,VC ++编译堆栈的大小为1 MB。堆栈提供更好的性能,但适用于较小数量的数据。通常,它不用于大型数据结构。这就是为什么在c ++中接受list / arrays / dictionaries / ect的函数通常会使用指针或对该结构的引用。通过值传递的参数被复制到堆栈上并且传递这样的结构经常会导致程序崩溃。
在您的示例中,您使用的是N int
,int
是4个字节。这使得A[N]
~4.7 MB的大小远远大于堆栈的大小。
答案 1 :(得分:2)
堆通过malloc和co分配动态增长。堆栈随着在运行程序的过程中进行的每个函数调用而增长。返回地址,自变量,局部变量通常存储在堆栈中(除了在某些处理器体系结构中,少数这些存储在寄存器中)。也可以(但不常见)动态分配堆栈空间。
堆和堆栈竞争使用相同的内存。你可以想到一个从左到右增长,另一个从右到左增长。如果不加以控制,它们可能会发生碰撞。通常限制堆栈超出某个界限。这是相对较小的,因为预计它对大多数调用只使用几个字节,并且只使用几个堆栈级别。限制很小但足以满足大多数任务。您可以通过更改构建设置(不是针对Linux ELF二进制文件)或通过调用setrlimit来扩展此限制。操作系统也可能施加限制,您可以更改。可能存在软限制和硬限制(http://www.nics.tennessee.edu/node/327)。
详细了解限制范围不属于问题的范围。底线是堆栈是有限的,它非常小,因为它与堆竞争实际内存,对于典型的应用程序,它不需要更大。