当类在构造函数中动态分配自身时,为什么会发生堆栈溢出而不是std :: bad_alloc?

own*_*fos 13 c++ stack-overflow bad-alloc

我制作了一个类,它使用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
}
Run Code Online (Sandbox Code Playgroud)

@Caleth问如果我将new Overflow()更改为new Overflow [100000],会发生什么,这给了我std::bad_alloc。根据答案,这岂不是还会给我堆栈溢出吗?

Nat*_*ica 18

因为您具有无限递归,所以发生了堆栈溢出。呼叫Overflow()使您Overflow()一次又一次地呼叫。这些函数调用需要进入堆栈。由于堆栈小于堆,因此所有构造函数调用都将耗尽堆栈空间,然后为所有正在创建的对象耗尽内存。


for*_*818 1

我对你的代码做了一个小修改:

#include <array>

template <size_t size>
class Overflow
{
private:
    Overflow* overflow;
    std::array<int,size> x;

public:
    Overflow()
    {
        overflow = new Overflow();
    }
};
Run Code Online (Sandbox Code Playgroud)

在魔盒上这个

int main()
{
    Overflow<1> overflow_happens;
}
Run Code Online (Sandbox Code Playgroud)

导致堆栈溢出引起的分段错误。

然而,

int main()
{    
    Overflow<10000> bad_alloc;
}
Run Code Online (Sandbox Code Playgroud)

结果是

terminate called after throwing an instance of 'std::bad_alloc'
  what():  std::bad_alloc

Aborted
Run Code Online (Sandbox Code Playgroud)

这里基本上有两种相互竞争的效果。作为构造函数的每个递归的第一个近似值(详细信息涉及更多):

  • aOverflow*在堆栈上
  • Overflow堆上的整个实例

因此,是否首先出现堆栈溢出或bad_alloc取决于Overflow. 对于小尺寸,您首先会遇到溢出,因为堆栈空间比堆空间更有限。

PS:我错过了您的编辑...如果您将new Overflow[100000]构造函数放入代码中,则会放大所需的堆空间,就像我通过添加array成员所做的那样。在堆栈上,您仍然有一个指针,因此您会更早地用完堆。