2

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

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];

我没有段错误。我大致了解为什么会这样:在第一个示例中,内存被放在堆栈上,而在动态情况下,它被放在堆上。

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

4

4 回答 4

6
bool primeNums[100000000];

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

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

有关如何operator new工作的更多信息,请参阅以下标准 [new.delete.single]:

要求的行为:

将非空指针返回到适当对齐的存储(3.7.3),否则抛出 bad_alloc 异常。此要求对该功能的替换版本具有约束力。

默认行为:

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

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

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

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

所以使用动态数组new,当空间不够时,bad_alloc默认会抛出,在这种情况下,你会看到一个异常而不是分段错误,当你的数组很大时,最好使用动态数组或标准容器比如向量。

于 2013-04-29T01:12:49.233 回答
1
bool primeNums[100000000];

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

该空间用于存储局部变量和静态变量,因此您必须保持温和,不要过度使用它。因为这是一个堆栈,所以所有分配都是连续的(分配之间没有空白空间)。

bool *primeNums = new bool[100000000];

在这种情况下,分配的内存是堆。这是可以分配大量新内存的空闲空间。

于 2013-04-29T01:24:53.380 回答
0

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

于 2013-04-29T01:14:08.507 回答
0

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

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

并且由于堆栈(非常)有限,这就是段错误的原因

于 2013-04-29T01:18:39.077 回答