下面的代码在一台2GB内存的机器上运行时会导致分段错误,但在一台4GB内存的机器上可以正常工作。
int main()
{
int c[1000000];
cout << "done\n";
return 0;
}
数组的大小仅为4Mb。在C++中,是否存在可用于数组大小的限制?
下面的代码在一台2GB内存的机器上运行时会导致分段错误,但在一台4GB内存的机器上可以正常工作。
int main()
{
int c[1000000];
cout << "done\n";
return 0;
}
数组的大小仅为4Mb。在C++中,是否存在可用于数组大小的限制?
你很可能会在这里遇到堆栈溢出。数组太大而无法适应程序的堆栈区域;在大多数主流桌面/服务器操作系统上,堆栈增长限制通常为8 MiB或1 MiB(用于用户空间代码)。 (正常的C ++实现使用asm堆栈来进行自动存储,即非 static
局部变量数组。当函数返回或异常通过它们传播时,这使得回收它们免费发生。)
如果你动态分配数组,如果你的计算机有足够的内存,你应该没有问题。
int* array = new int[1000000]; // may throw std::bad_alloc
请记住,即使您的函数通过异常退出,这也需要您手动delete[]
数组以避免内存泄漏。在现代C++中强烈不建议使用手动的new/delete,而应该使用RAII。
更好的解决方法是使用std::vector<int> array
(cppreference)。如果您知道它将增长多大,可以为1000000个元素预留空间。或者甚至可以resize
它以默认构造它们(即对内存进行零初始化,与当您声明没有初始值器的普通C风格数组不同),例如std::vector<int> array(1000000)
。
当std::vector
对象超出作用域时,其析构函数将为您释放存储空间,即使它是通过父函数捕获子函数的异常退出的。
在 C 或 C++ 中,局部对象通常分配在堆栈上。由于你正在在堆栈上分配一个大数组,超出了堆栈的处理能力,因此会导致 stackoverflow。
不要在堆栈上分配,使用其他地方代替。这可以通过使对象成为全局变量或将其分配到全局堆中来实现。如果您不从任何其他编译单元中使用全局变量,则全局变量是可以接受的。为确保意外情况下不会发生这种情况,请添加 static 存储说明符,否则只需使用堆即可。
这将在 BSS 段中分配,该段是堆的一部分。由于它在静态存储中,如果不指定其他方式,则会进行零初始化,而不像局部变量(自动存储)包括数组。
static int c[1000000];
int main()
{
cout << "done\n";
return 0;
}
非零初始化器会让编译器在DATA段分配空间,这也是堆的一部分。数组初始化器中的所有数据(包括所有隐式的末尾零)都将占用可执行文件中的空间,而不仅仅是大小为零的BSS段。
int c[1000000] = {1, 2, 3};
int main()
{
cout << "done\n";
return 0;
}
这将在堆中的某个未指定位置进行分配:
int main()
{
int* c = new int[1000000]; // size can be a variable, unlike with static storage
cout << "done\n";
delete[] c; // dynamic storage needs manual freeing
return 0;
}
new
分配内存时,随处使用delete
是一个好的习惯。但如果你确定只在一个地方(比如在主函数中)分配内存,那么严格来说并不需要使用delete
- 内存会在程序退出主函数时被自动释放,即使没有显式使用delete
。 - Gunther Piez此外,如果您在大多数UNIX和Linux系统上运行,可以通过以下命令临时增加堆栈大小:
ulimit -s unlimited
但是要小心,记忆是有限的资源,伴随着强大的力量而来的是伟大的责任 :)
#include <vector>
#include <iostream>
int main() {
std::vector<int> c(1000000);
std::cout << "done\n";
return 0;
}
#include <vector>
#include <array>
#include <iostream>
int main() {
std::vector<std::array<std::array<int, 123>, 456>> c(100);
std::cout << "done\n";
return 0;
}
int c [100] [456] [123];
相同的行为(除了向量在堆上分配而不是堆栈),您可以像在普通数组中一样访问元素c [10] [20] [30]
。上面的示例还在堆上分配数组,这意味着您可以拥有整个内存大小的数组大小,而不受堆栈大小的限制。&c [0]
或只需c.data()
。还有一种方法对我很有效!你可以通过更改数组的数据类型来减小其大小:
int main()
{
short c[1000000];
cout << "done\n";
return 0;
}
或者
int main()
{
unsigned short c[1000000];
cout << "done\n";
return 0;
}