以下代码给出了分段错误:
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];
我没有遇到段错误。我有一个大致的想法,为什么会这样:在第一个例子中,内存被放在堆栈上,而在动态情况下,它被放在堆上。
你能更详细地解释一下吗?
答案 0 :(得分:5)
bool primeNums[100000000];
用完了所有stack
空间,因此,由于没有足够的堆栈空间来分配大尺寸的静态数组,因此会出现分段错误。
动态数组在heap
上分配,因此,不容易得到分段错误。动态数组是使用C ++中的new
创建的,它将调用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
,在这种情况下,当您的数组大小时,您将看到异常而不是分段错误是巨大的,最好使用动态数组或标准容器,如矢量。
答案 1 :(得分:1)
bool primeNums[100000000];
此声明在stack space中分配内存。堆栈空间是在启动应用程序时分配的内存块。它通常在几千字节或兆字节的范围内(这取决于语言实现,编译器,操作系统和其他因素)。
此空间用于存储本地和静态变量,因此您必须温和且不要过度使用它。因为这是一个堆栈,所有分配都是连续的(分配之间没有空的空间)。
bool *primeNums = new bool[100000000];
在这种情况下,分配的内存是堆。这是无空间的,可以分配大量的新内存。
答案 2 :(得分:0)
某些编译器或操作系统会限制堆栈的大小。在Windows上,默认值为1 MB,但可以更改。
答案 3 :(得分: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
并且由于堆栈(非常)受限,这就是segfault的原因