使用C数组时出现堆栈溢出错误

4
当我定义时
void tfooo(){
int arr[SOME_LARGE_NUMBER];
// some code here
}

我遇到了栈溢出的问题,但是当我添加static关键字时

void tfooo(){
static int arr[SOME_LARGE_NUMBER];
// some code here
}

一切都很好。

有何不同?静态数组与动态数组不是总是在堆栈上定义的吗?


1
你可能会发现这个链接有帮助:https://dev59.com/iXVD5IYBdhLWcg3wGHeu - StaticBeagle
@DevSolar 是从 C 的角度提问的。我也知道这两个例子都不是动态分配,而是静态的。问题是为什么只在第一个例子中出现堆栈溢出错误。 - Benny K
可能是为什么在C中声明变量或函数为静态的?的重复问题。 - Bo Persson
1
因为静态数组 - 它比当前函数调用更长寿 - 是在二进制文件本身中分配的(ELF:.data / .bss 部分)。所以没有涉及到堆栈。 - DevSolar
@DevSolar:我认为“动态”的含义有些混淆。C语言没有使用这个术语。C语言有“可变长度数组”(VLAs),其长度在运行时确定。具有自动存储期限的数组(或任何其他对象)在进入封闭块时会分配内存。具有静态存储期限的对象在程序启动时分配内存,并且仅在程序终止时释放。 (所有静态对象都具有固定大小,但自动对象可以具有固定或“动态”大小。) - Keith Thompson
显示剩余5条评论
2个回答

2

通常情况下,声明为自动的对象会被分配在栈上(相对较小的内存),而声明为static的对象则会被分配在其他地方。

需要注意的是,这取决于您的计算机和编译器。


“取决于您的机器和编译器”是应该强调的部分。C11标准-6.2.4对象的存储期仅说明了对象可以被有效访问的时间,而不是它们被分配的位置。 - David C. Rankin

1
我正在生成静态版本和非静态版本的汇编代码,唯一的区别在于静态版本中不存在该变量。我认为它已被删除,因为在我的测试中没有使用它。
你是否在你的测试中使用了这个变量?也许优化器已经在静态版本中删除了这个变量。
我正在使用gcc。要构建汇编代码,请传递-S参数:
gcc -S main.c

这是用于非静态版本的测试代码:

#define SOME_LARGE_NUMBER (100000000000000000)

int arr[SOME_LARGE_NUMBER];

int main(const int argc, const char* argv[]) {
    return 0;
}

这是关于静态版本的内容:
#define SOME_LARGE_NUMBER (100000000000000000)

static int arr[SOME_LARGE_NUMBER];

int main(const int argc, const char* argv[]) {
    return 0;
}

这是我得到的差异:
$ diff main.static.s main.nostatic.s 
23a24
>   .comm   _arr,400000000000000000,4 ## @arr

根据您提供的信息,我能了解到以下内容。请问您能否提供更多关于您的代码的细节?
编辑:在附加的图像中,我们可以看到Windows应用程序的内存布局。当我们在函数中使用static修饰符时,它被存储在.data段中,而不是程序堆栈中,因此您不会遇到堆栈溢出问题。在编译时,数组的大小已知,因此二进制映像为数据存储足够的空间。两个版本中,你的EXE文件大小是多少?如果我没有错的话,静态版本的EXE文件大小将比非静态版本大得多。我假设数组的大小在加载二进制文件时被保留到数据段中。但是,在使用非静态版本时,它取决于设置堆栈的内存量。您可以使用命令行编译时的标志"/F"来修改此大小(请参阅此链接 https://msdn.microsoft.com/en-us/library/tdkhxaks.aspx)。我没有安装Windows虚拟机进行双重检查。

enter image description here

总的来说,静态变量不会存储在堆栈中,因此使用静态版本时不会导致堆栈溢出。

我认为他们在谈论arr是在函数内部定义的。 - M.M
我不知道,我看到的代码只有声明,没有更多信息。我已经将这段代码在我的机器(x86_64架构)上重新运行了一遍。这是我能说的唯一的事情。 - user4207183
@Alejandro Visiedo 首先,我的代码在一个函数内。其次,我正在使用 x64 机器上的 Visual Studio 2015。 - Benny K

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接