大数组大小的分段错误

May*_*ank 103 c++ arrays segmentation-fault

以下代码在2Gb机器上运行时给出了分段错误,但在4GB机器上运行.

int main()
{
   int c[1000000];
   cout << "done\n";
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

阵列的大小只有4Mb.可以在c ++中使用的数组大小是否有限制?

Cha*_*via 115

你可能只是在这里得到一个堆栈溢出.该数组太大,无法放入程序的堆栈地址空间.

如果你在堆上分配数组,你应该没问题,假设你的机器有足够的内存.

int* array = new int[1000000];

但请记住,这将需要您到delete[]阵列.更好的解决方案是使用std::vector<int>并将其大小调整为1000000个元素.

  • 给定的代码在堆栈上分配,因为它在编译时被指定为具有恒定数量元素的数组.值只能放在具有malloc,new等的堆上. (15认同)
  • 所有自动变量都在堆栈上分配.如果查看可反汇编,您将看到从堆栈指针中减去局部变量的大小.当您调用malloc或calloc或任何内存功能时,功能会发现并找到足够大的内存块来满足您的要求. (5认同)
  • 感谢您的回答,但是您能否解释一下为什么数组在堆栈上分配,为什么不在主程序内存中分配。 (2认同)
  • @saurabhagarwal堆不动.它甚至不是一个连续的记忆区域.分配器只返回一个符合你的大小要求的空闲内存块[堆栈和堆的内容和位置是什么?](http://stackoverflow.com/q/79923/995714) (2认同)

Gun*_*iez 51

在C或C++中,通常在堆栈上分配本地对象.您正在堆栈上分配一个大型数组,超过堆栈可以处理的数组,因此您将获得堆栈溢出.

不要在堆栈上分配本地,而是使用其他地方.这可以通过使对象全局化或在全局堆上分配它来实现.如果不使用任何其他编译单元,则全局变量很好.要确保不会发生这种情况,请添加静态存储说明符,否则只需使用堆.

这将在BSS段中分配,这是堆的一部分:

static int c[1000000];
int main()
{
   cout << "done\n";
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将在DATA段中分配,这也是堆的一部分:

int c[1000000] = {};
int main()
{
   cout << "done\n";
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

这将在堆中的某个未指定位置分配:

int main()
{
   int* c = new int[1000000];
   cout << "done\n";
   return 0;
}
Run Code Online (Sandbox Code Playgroud)

  • @meowsqueak当然,在你用`new`分配的地方`删除`是一个好习惯.但是如果你确定你只分配了一次内存(比如在main中),那么严格来说它是不需要的 - 即使没有明确的`delete`,也可以保证在main的出口处释放内存. (6认同)

RSF*_*on7 12

此外,如果您在大多数UNIX和Linux系统中运行,则可以通过以下命令临时增加堆栈大小:

ulimit -s unlimited
Run Code Online (Sandbox Code Playgroud)

但要小心,记忆是一种有限的资源,并且有很大的力量来承担很大的责任:)

  • 这是解决方案,但我建议所有人在删除程序堆栈大小的默认限制时要极其谨慎。您不仅会遇到性能严重下降的情况,而且系统可能会崩溃。例如,我尝试在具有 4GB RAM 的计算机上使用快速排序对包含 16 000 000 个整数元素的数组进行排序,但我的系统几乎被杀死。哈哈 (2认同)