我知道可变长度数组(VLA)是technically not allowed in C++。但是,除非您使用-pedantic
关键字,否则不会收到警告。即使这样,您也只会收到警告。
尽管我还没有找到具体的参考,但是我很确定VLAs
是在堆栈上分配的,而动态数组是在堆上分配的。
在调试通常接收不到100 mb消息的函数时,我遇到了以下情况:无法使用gdb访问数组的 middle ,而开始和结束都可以。我意识到,在堆栈上分配时,我可能会更快地遇到内存或地址空间限制。
为什么在这么低的字节数下此代码段错误? 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] = '\0';
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;
}
答案 0 :(得分:2)
堆栈通常是固定大小的。如果该大小很大,则在创建线程时保留该大小,那么您将无法在内存不足之前创建很多线程。
该堆栈是为临时数据的少量分配而设计的,应在堆上执行寿命较长的数据和较大的分配。
通常,堆栈大小在Linux上约为8mb,在Windows上约为1mb。
您可能能够分配超出可用堆栈大小的空间,并且仅当尝试访问超出可用堆栈大小的程序时,程序才会崩溃。这取决于平台,例如,在Windows上,一旦分配的内存超出堆栈中的容量,就会出现堆栈溢出异常。