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

时间:2018-10-20 18:32:21

标签: c++ arrays gcc memory

我知道可变长度数组(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;
}

1 个答案:

答案 0 :(得分:2)

堆栈通常是固定大小的。如果该大小很大,则在创建线程时保留该大小,那么您将无法在内存不足之前创建很多线程。

该堆栈是为临时数据的少量分配而设计的,应在堆上执行寿命较长的数据和较大的分配。

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

您可能能够分配超出可用堆栈大小的空间,并且仅当尝试访问超出可用堆栈大小的程序时,程序才会崩溃。这取决于平台,例如,在Windows上,一旦分配的内存超出堆栈中的容量,就会出现堆栈溢出异常。