TGViewer
Грокаем C++ Грокаем C++ @grokaemcpp · 9.35K subscribers
Post #707 4.6K
​​Что будет если бросить исключение в деструкторе? Ходим по тонкому льду.
#опытным

Но что же делать, если у вас есть безудержное желание бросить исключение в деструкторе? Возможно ли это как-то безопасно сделать?


На самом деле есть один вариант. Вряд ли вам хочется прям явно написать "throw" в деструкторе. Думаю, что на самом деле вы хотите использовать в деструкторе функцию, которая потенциально может бросить исключение:

constexpr std::string_view defaultSymlinkPath = "/system/logs/log.txt";

class Logger
{
std::string m_fileName;
std::ofstream m_fileStream;

Logger(const char *filename)
: m_fileName { filename }
, m_fileStream { m_fileName }
{}

void Log(std::string_view);

~Logger() noexcept(false)
{
fileStream.close();
std::filesystem::create_symlink(m_fileName, defaultSymlinkPath);
}
};


Логгер может писать в файл с нестандартным именем, но хочет в деструкторе сделать симлинк на него в системной директории /system/logs/log.txt.

Одна проблема - std::filesystem::create_symlink может кинуть исключение, если например прав доступа к директории нет.

Было бы классно определять, находится ли сейчас программа в состоянии разворачивания стека. Если находится, то не делать опасные мувы, а если нет, то гуляй душа.

И такой инструмент есть, называется он std::uncaught_exception(). Это функция проверяет, есть ли сейчас живой объект исключения и исполнение еще не дошло до блока catch. То есть программа находится в режима разворачивания стека. И можно на основе этого знания какую-то логику строить.

Например, не создавать симлинк в логгере, если есть живой объект исключений:

~Logger()
{
fileStream.close();
if (!std::uncaught_exception())
{
std::filesystem::create_symlink(m_fileName, defaultSymlinkPath);
}
}


В этом случае мы не будем вызывать опасную функцию, потому что это потенциально может привести к std::terminate.

Исключения - это все-таки исключительные ситуации. При их обработке важно правильно себя повести и сделать хоть что-то, но сохранить работоспособность программы, чем жонглировать ножами и в итоге выткнуть себе глаз.

И std::uncaught_exception() позволяет динамически изменять поведение программы, если вы уже попали в исключительную ситуацию.

Однако в C++17 эта функция призвана устаревшей и была удалена в C++20. В следующий раз посмотрим, почему так и что пришло ей на замену.

Walk on a thin ice. Stay cool.

#cpp17 #cpp20
  • 👍 31
  • 🔥 13
  • ❤ 8
More from @grokaemcpp
  1. Oct 12, 2026​​WAT #новичкам Как вы думаете, результат выражения: bool math = -1 < 1U; будет правдой ил…
  2. Oct 8, 2026​​Strict weak ordering #опытным На первый взгляд, всё выглядит рабочим: мы создаём 40 зака…
  3. Oct 7, 2026​​Где-то баг... #опытным Вот вам код: struct Order { int price; int id; }; int main() { st…
  4. Oct 5, 2026Откуда spurious wakeup на кондваре? #опытным У кондваров есть метод std::condition_variabl…
  5. Oct 1, 2026​​Stacktrace. Tips #опытным Чтобы полноценно работать со стандартными трейсами, нужно знат…
  6. Sep 28, 2026​​Stacktrace #опытным Одна из проблема исключений - непонятно, откуда оно прилетело. Ну да…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →