I made a class that recursively creates itself using new
(just for fun!), expecting that this will throw std::bad_alloc
due to infinite dynamic allocation (heap overflow). But stack overflow happened instead of std::bad_alloc
. Why does this happen?
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 asked what happens if I change new Overflow() to new Overflow[100000], and this gave me std::bad_alloc
. According to the answers, shouldn't this also give me stack overflow?
I made a small modification to your code:
#include <array>
template <size_t size>
class Overflow
{
private:
Overflow* overflow;
std::array<int,size> x;
public:
Overflow()
{
overflow = new Overflow();
}
};
On wandbox this
int main()
{
Overflow<1> overflow_happens;
}
results in a segmentation fault caused by overflow of the stack.
However, this
int main()
{
Overflow<10000> bad_alloc;
}
results in
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
Aborted
You basically have two competing effects here. As a first approximation (details are a bit more involved) you have for each recursion of the consturctor:
Overflow*
on the stackOverflow
instance on the heapHence whether you first get a stack overflow or bad_alloc
depends on the size of Overflow
. And for small sizes you'll first get a overflow, because stack space is much more limited than heap space.
PS: I missed your edit... if you place new Overflow[100000]
in the constructor in your code you amplify the required heap space, just as I did by adding the array
member. On the stack you still have a single pointer and hence you run out of heap much earlier.