← Назад ко всем вопросам

Что будет при появлении в деструкторе исключения

1️⃣ Как кратко ответить

Если в деструкторе возникает исключение и оно не обрабатывается внутри деструктора, это может привести к завершению программы с вызовом std::terminate(), если в процессе разворачивания стека уже было активное исключение. Это происходит потому, что в C++ не допускается наличие двух активных исключений одновременно.

2️⃣ Подробное объяснение темы

В C++ деструкторы используются для освобождения ресурсов, когда объект выходит из области видимости или уничтожается. Деструкторы вызываются автоматически, и их основная задача — корректно завершить работу объекта, освободив все ресурсы, которые он использовал.

Когда в деструкторе возникает исключение, это может привести к серьезным проблемам, особенно если в процессе разворачивания стека уже было активное исключение. В C++ не допускается наличие двух активных исключений одновременно. Если это происходит, программа завершает работу, вызывая std::terminate(). Это поведение обусловлено тем, что система обработки исключений не может корректно обработать два исключения одновременно.

Рассмотрим пример кода, чтобы понять, как это работает:

#include <iostream>
#include <stdexcept>
​
class Example {
public:
    ~Example() {
        // Попытка выбросить исключение в деструкторе
        throw std::runtime_error("Exception in destructor");
    }
};
​
int main() {
    try {
        Example ex;
        throw std::runtime_error("Exception in main");
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}
  1. В этом примере класс Example имеет деструктор, который выбрасывает исключение std::runtime_error.
  2. В функции main создается объект ex типа Example.
  3. Затем выбрасывается исключение std::runtime_error с сообщением "Exception in main".
  4. Исключение перехватывается блоком catch, и выводится сообщение "Caught exception: Exception in main".
  5. После этого начинается процесс разворачивания стека, и вызывается деструктор объекта ex.
  6. В деструкторе выбрасывается второе исключение, что приводит к вызову std::terminate(), так как в процессе разворачивания стека уже было активное исключение.

Чтобы избежать таких ситуаций, рекомендуется не выбрасывать исключения из деструкторов. Если в деструкторе может возникнуть ошибка, лучше обработать её внутри деструктора, например, записав сообщение об ошибке в лог или используя другие механизмы обработки ошибок, которые не связаны с выбросом исключений. Это позволяет избежать завершения программы и обеспечивает более предсказуемое поведение.

Тема: Исключения / noexcept / Safety
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки