当 class 在构造函数中动态分配自身时,为什么会发生堆栈溢出而不是 std::bad_alloc?
When a class dynamically allocates itself at constructor, why does stack overflow happen instead of std::bad_alloc?
我做了一个 class,它使用 new
递归地创建自己(只是为了好玩!),预计这会由于无限动态分配(堆溢出)而抛出 std::bad_alloc
。但是发生了堆栈溢出而不是 std::bad_alloc
。为什么会这样?
class Overflow
{
private:
Overflow* overflow;
public:
Overflow()
{
overflow = new Overflow();
}
};
int main()
{
Overflow overflow_happens; // stack overflow happens instead of std::bad_alloc exeption
}
@Caleth 问如果我将 new Overflow() 更改为 new Overflow[100000] 会发生什么,这给了我 std::bad_alloc
。根据答案,这不应该也让我堆栈溢出吗?
因为你在递归地重复调用构造函数,一个方法。方法调用被推送到调用堆栈。由于堆栈大小远小于可用堆,因此调用堆栈会在堆用完之前溢出。
发生堆栈溢出是因为您有无限递归。调用 Overflow()
会使您一次又一次地调用 Overflow()
。这些函数调用需要进入堆栈。由于您的堆栈小于您的堆,因此在您 运行 您正在创建的所有对象内存不足之前,所有这些构造函数调用都会 运行 内存不足 space。
我对你的代码做了一点小修改:
#include <array>
template <size_t size>
class Overflow
{
private:
Overflow* overflow;
std::array<int,size> x;
public:
Overflow()
{
overflow = new Overflow();
}
};
在 wandbox 这个
int main()
{
Overflow<1> overflow_happens;
}
导致栈溢出导致段错误。
然而,this
int main()
{
Overflow<10000> bad_alloc;
}
结果
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
这里基本上有两种相互竞争的效果。作为第一个近似值(涉及更多细节),构造函数的每次递归:
- 一个
Overflow*
在堆栈上
- 堆上的整个
Overflow
实例
因此,您首先得到堆栈溢出还是 bad_alloc
取决于 Overflow
的大小。对于小尺寸,您首先会溢出,因为堆栈 space 比堆 space.
更受限制
PS: 我错过了你的编辑...如果你将 new Overflow[100000]
放在代码的构造函数中,你会放大所需的堆 space,就像我添加 array
成员一样。在堆栈上,您仍然只有一个指针,因此您 运行 更早地离开堆。
我做了一个 class,它使用 new
递归地创建自己(只是为了好玩!),预计这会由于无限动态分配(堆溢出)而抛出 std::bad_alloc
。但是发生了堆栈溢出而不是 std::bad_alloc
。为什么会这样?
class Overflow
{
private:
Overflow* overflow;
public:
Overflow()
{
overflow = new Overflow();
}
};
int main()
{
Overflow overflow_happens; // stack overflow happens instead of std::bad_alloc exeption
}
@Caleth 问如果我将 new Overflow() 更改为 new Overflow[100000] 会发生什么,这给了我 std::bad_alloc
。根据答案,这不应该也让我堆栈溢出吗?
因为你在递归地重复调用构造函数,一个方法。方法调用被推送到调用堆栈。由于堆栈大小远小于可用堆,因此调用堆栈会在堆用完之前溢出。
发生堆栈溢出是因为您有无限递归。调用 Overflow()
会使您一次又一次地调用 Overflow()
。这些函数调用需要进入堆栈。由于您的堆栈小于您的堆,因此在您 运行 您正在创建的所有对象内存不足之前,所有这些构造函数调用都会 运行 内存不足 space。
我对你的代码做了一点小修改:
#include <array>
template <size_t size>
class Overflow
{
private:
Overflow* overflow;
std::array<int,size> x;
public:
Overflow()
{
overflow = new Overflow();
}
};
在 wandbox 这个
int main()
{
Overflow<1> overflow_happens;
}
导致栈溢出导致段错误。
然而,this
int main()
{
Overflow<10000> bad_alloc;
}
结果
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
这里基本上有两种相互竞争的效果。作为第一个近似值(涉及更多细节),构造函数的每次递归:
- 一个
Overflow*
在堆栈上 - 堆上的整个
Overflow
实例
因此,您首先得到堆栈溢出还是 bad_alloc
取决于 Overflow
的大小。对于小尺寸,您首先会溢出,因为堆栈 space 比堆 space.
PS: 我错过了你的编辑...如果你将 new Overflow[100000]
放在代码的构造函数中,你会放大所需的堆 space,就像我添加 array
成员一样。在堆栈上,您仍然只有一个指针,因此您 运行 更早地离开堆。