#опытным
Работа с исключениями - целое искусство. В этой теме куча фишек, которые помогут извлекать из исключений максимум пользы.
Пусть вы хотите работать с какой-то сущностью в коде эксклюзивно:
void func(std::shared_ptr<Resource> res) {
if (res->TryToAcquire()) {
// do dirty things
res->Release();
} else {
// you don't have permission to do dirty, so return
return;
}
}Что будет, если в этом коде в результате обработки эксклюзивно захваченного ресурса произойдет исключение?
Правильно, утечка. Утечка ресурса. Так как вы его явно не освободили через метод Release, вы его больше не сможете захватить и он так и останется в подвешанном состоянии.
Хорошо бы отловить исключение и освободить ресурс. Однако привычная обработка исключений тут особо не поможет. Мы на этом слое вызовов не можем адекватно обработать исключение. У нас просто недостаточно информации и полномочий, чтобы принять решение, как действовать дальше
То есть нам как-то нужно сделать 2 вещи одновременно: дать исключению выйти наружу и освободить ресурс. Плюс к этому хочется залогировать ошибку.
Автоматически освободить ресурс нам поможет RAII обертка, которая освободит ресурс в деструкторе, если его получилось захватить, а залогировать ошибку поможет совместное использование catch + простой вызов "throw".
void func(std::shared_ptr<Resource> res) {
auto raii_res = RaiiWrapper(res);
if (raii_res->TryToAcquire()) {
try {
// do dirty things
} catch (const std::exception& ex) {
Log("Houston, we have a problem");
throw;
}
} else {
// you don't have permission to do dirty, so return
return;
}
}Инструкция throw делает единственную вещь - пробрасывает то же самое исключение выше по стеку вызовов.
Получается, что можно не до конца обрабатывать исключение, а сделать свои дела и пробросить исключение дальше.
Don't leak your resources. Stay cool.
#cppcore