【发布时间】:2016-12-05 19:43:14
【问题描述】:
Linux下启动
ulimit -s 1024
限制堆栈大小。
首先是一个可以运行的程序:
#include <stdio.h>
static int calc(int c,int *array)
{
if (array!=NULL) {
if (c<=0) {
array[0]=1;
return 1;
}
calc(c-1,array);
array[c]=array[c-1]+3;
return array[c];
} else {
int a[2500+c];
calc(c-1,a);
a[c]=a[c-1]+3;
return a[c];
}
}
int main()
{
int result;
result = calc(1000,NULL);
printf("result = %d\n",result);
}
现在,如果我将 int a[2500+c]; 更改为 int a[2500];,那么程序会因堆栈溢出(分段错误)而崩溃。
我试过这个
- gcc-4.4.7 -O0, gcc-4.4.7 -O2, gcc-4.4.7 -O3
- gcc-4.8.4 -O0, gcc-4.8.4 -O2, gcc-4.8.4 -O3
- gcc-4.9.3 -O0, gcc-4.9.3 -O2, gcc-4.9.3 -O3
如果我使用
ulimit -s 1024
然后带有int a[2500]; 的版本崩溃,而带有int a[2500+c]; 的版本可以工作。
为什么使用可变长度数组 (int a[2500+c];) 的程序版本比使用固定长度数组 (int a[2500];) 的程序版本占用更少的堆栈空间?
【问题讨论】:
-
注意:如果您(例如)在 main 中使用
calc(20,NULL);,该程序也适用于这两种情况。第二个版本(使用固定长度数组)只使用了 lots 更多的堆栈。 -
两个版本对我来说都没有错误。
-
约翰:哪个编译器?
-
我可以用 gcc 4.8.4
-O0重现这个。在-O3上,两个版本都可以正常工作。原因是编译器在函数序言中无条件分配int a[2500];和-O0,而不检查array != NULL -
也许如果你说
a[2500]编译器会尝试将数组放入堆栈,但如果你说a[2500+c]它会使用堆,因为 a 的大小在编译时间。
标签: c stack local-storage