为什么我只能在C++中使用可变长度数组分配小于 10 mb 的内存?

Why can I only assign less than 10 mb using variable-lenght array in C++?

本文关键字:小于 分配 数组 mb 内存 C++ 为什么      更新时间:2023-10-16

我知道可变长度数组(VLA(在技术上是不允许C++的。但是,除非您使用-pedantic关键字,否则您不会收到警告。即便如此,您也只会收到警告。

虽然我没有找到这方面的具体参考,但我很确定VLAs是在堆栈上分配的,而动态数组是在堆上分配的。

在调试一个接收通常小于 100 mb 的消息的函数时,我遇到了无法使用 gdb 访问数组中间的情况,而开头和结尾都可以。我意识到在堆栈上分配时,我可能会更快地遇到内存或地址空间限制。

为什么这段代码在如此少的字节数时会出现段错误?VLA 的大小是否有任何限制?为什么段错误发生在访问而不是分配上?为什么我可以使用 gdb 访问数组的末尾(在此示例代码中,在其他更大的程序中,我也可以访问开始(?

我用 clang 和 gcc 得到了相同的结果。

# include <iostream>
# include <vector>
using std::cout;
using std::endl;

void foo_a (int n) {
/* on stack */
cout << "a: (C),   n = " << n << endl;
char buffer[n]; buffer[n] = '';
cout << (void*)buffer << endl;
for (int i = 0; i < n; i++) {
buffer[i] = (char) i;
}
}
void foo_b (int n) {
/* on heap */
cout << "b: (C++), n = " << n << endl;
char * buffer = new char[n];
for (int i = 0; i < n; i++) {
buffer[i] = (char) i;
}
cout << (void*)buffer << endl;
delete [] buffer;
}
int main (int, char**) {
int Ns[] = { 1024, 123123, 10586239 };
for (int n : Ns) {
foo_b (n);
foo_a (n);
}
return 0;
}

堆栈通常是固定大小。由于此大小是在创建线程时保留的,如果大小很大,因此在内存不足之前将无法创建非常多的线程。

堆栈设计用于临时数据的少量分配,应在堆上执行长期数据和大型分配。

通常,Linux上的堆栈大小约为8mb,Windows上的堆栈大小约为1mb。

您可以分配超过可用堆栈大小的分配,并且程序仅在尝试访问超出可用堆栈大小时崩溃。这取决于平台,例如在Windows上,一旦您分配的超过堆栈中容纳的内容,您就会收到堆栈溢出异常。