为什么大型静态数组会给出段错误,而动态数组不会?(C++)

Why does a large static array give a seg-fault but dynamic doesn't? (C++)

本文关键字:数组 动态 C++ 大型 错误 段错误 为什么 静态      更新时间:2023-10-16

下面的代码给了我一个分段错误:

bool primeNums[100000000]; // index corresponds to number, t = prime, f = not prime
for (int i = 0; i < 100000000; ++i)
{
    primeNums[i] = false;
}

但是,如果我将数组声明更改为动态:

bool *primeNums = new bool[100000000];

我一点毛病都没有。我对为什么会这样有一个大致的想法:在第一个例子中,内存被放在堆栈上,而在动态情况下,它被放在堆上。

你能更详细地解释一下吗?

bool primeNums[100000000];

用完了所有的stack空间,因此,由于没有足够的堆栈空间来分配一个巨大的静态数组,您将出现分段错误。

动态阵列是在heap上分配的,因此不容易出现分割错误。动态数组是用C++中的new创建的,它会调用operator new来分配内存,然后调用构造函数来初始化分配的内存。

关于operator new如何工作的更多信息引用自以下标准[new.delete.single]:

所需行为:

返回一个指向适当对齐存储的非null指针(3.7.3(,或者否则抛出一个bad_alloc异常。此要求对该功能的替换版本具有约束力。

默认行为:

--执行循环:在循环中,函数首先尝试分配请求的存储。尝试是否涉及对标准C库函数malloc的调用是未指定的。

--如果尝试成功,则返回指向已分配存储的指针。否则,如果set_new_handler((的最后一个参数是空指针,则抛出bad_alloc。

--否则,函数调用当前的new_handler(18.4.2.2(。如果被调用的函数返回,则循环重复。

--当尝试分配请求的存储成功或调用的new_handler函数未返回时,循环终止。

因此,将动态数组与new一起使用,当空间不足时,默认情况下会抛出bad_alloc,在这种情况下,您会看到异常而不是分段错误,当您的数组大小巨大时,最好使用动态数组或向量等标准容器。

bool primeNums[100000000];

此声明在堆栈空间中分配内存。堆栈空间是在启动应用程序时分配的内存块。它通常在几千字节或兆字节的范围内(这取决于语言实现、编译器、操作系统和其他因素(。

这个空间用于存储本地和静态变量,所以你必须温和,不要过度使用它。因为这是一个堆栈,所以所有分配都是连续的(分配之间没有空格(。

bool *primeNums = new bool[100000000];

在这种情况下,分配的内存是堆。这是一个空闲空间,可以在其中分配新的大型内存卡盘。

某些编译器或操作系统会限制堆栈的大小。在windows上,默认值为1MB,但可以更改。

在第一种情况下,您在堆栈上分配内存:

bool primeNums[100000000]; // put 100000000 bools on stack
for (int i = 0; i < 100000000; ++i)
{
    primeNums[i] = false;
}

然而,这是堆上的分配:

bool *primeNums = new bool[100000000]; // put 100000000 bools in the heap

由于堆栈(非常(有限,这就是segfault

的原因