为什么一个C程序崩溃,如果一个大的variables被声明?

我在Microsoft Visual Studio Express 2012中编译了以下C程序:

int main() { int a[300000]; return 0; } 

这与msvcr110d.dll!__ crtFlsGetValue()中的堆栈溢出崩溃。

如果我将数组大小从300,000更改为200,000,它可以正常工作(因为这个简单的程序可以说是“工作”,因为它没有任何操作)。

我在Windows 7上运行,也尝试过在Cygwin下使用gcc,它会产生相同的行为(在这种情况下是seg故障)。

有没有搞错?

因为它被分配在堆栈上,并且堆栈的大小有限,所以显然不足以容纳300000个整数。

使用堆分配a malloc

 int* a = malloc(sizeof(int) * 300000); // ... free(a); 

堆可以容纳比堆栈多得多的堆。

C中的自动对象使用的空间大小(“堆栈大小”)有特定于平台的限制。 大于该大小的对象(可能是嵌入式平台上的几千字节,桌面机器上的几兆字节)不能被声明为自动对象。 让它们变成静态或动态的。

同样,函数调用的深度也是有限的,特别是递归。

检查您的编译器和/或平台文档,以获取有关实际大小的详细信息,以及有关如何更改它的详细信息。 (例如在Linux上检查ulimit 。)

局部变量从堆栈中声明空间。 所以,如果你分配足够大的东西,堆栈将不可避免地溢出。

线程堆栈的大小传统上受操作系统的限制,因为对每个进程可用的虚拟地址空间量有限制。

由于分配给线程堆栈的虚拟地址空间一旦被分配就不能被改变,除了为每个线程分配一个相当大但是有限的块以外,没有其他的策略 – 即使大多数线程只使用很少的块。

同样,对于进程允许产生的线程数也有一个有限的限制。

据推测,这里的限制是1MB,然后Windows将线程的数量限制为 – 比如256,这意味着32位进程可用的3GB虚拟地址空间的256MB分配给线程堆栈 – 或者把另一个方式,1/12。

在64位系统中,显然有更多的虚拟空间可供使用,但是为了快速检测和终止无限递归,有一个限制仍然是合理的。