Когда класс динамически размещает себя в конструкторе, почему переполнение стека происходит вместо std :: 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
}
@Caleth спросил, что произойдет, если я заменю новый Overflow() на новый Overflow [100000], и это дало мне std::bad_alloc
. Согласно ответам, не должно ли это также привести к переполнению стека?
Ответы
Ответ 1
Переполнение стека происходит из-за бесконечной рекурсии. Вызов Overflow()
заставляет вас вызывать Overflow()
снова, снова и снова. Эти вызовы функций должны идти в стек. Так как ваш стек меньше вашей кучи, вам не хватит места в стеке для всех этих вызовов конструктора, прежде чем вам не хватит памяти для всех объектов, которые вы создаете.
Ответ 2
Потому что вы рекурсивно вызываете конструктор, метод, многократно. Вызовы методов переносятся в стек вызовов. Поскольку размер стека намного меньше доступной кучи, стек вызовов переполняется до того, как куча заканчивается.
Ответ 3
Я сделал небольшую модификацию вашего кода:
#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;
}
приводит к ошибке сегментации, вызванной переполнением стека.
Тем не менее, это
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
. А для небольших размеров вы сначала получите переполнение, потому что пространство стека намного более ограничено, чем пространство кучи.
PS: я пропустил ваше редактирование... если вы поместите new Overflow[100000]
в конструктор в вашем коде, вы увеличите требуемое пространство кучи, как я сделал, добавив элемент array
. В стеке у вас все еще есть один указатель и, следовательно, вы исчерпали кучу намного раньше.