Background of the question:
The exception handling mechanism was introduced in C++ to provide more reliable and structured error handling, as opposed to return codes. Over the years, the syntax has expanded, and type specifiers like noexcept have been introduced to control the cancellation of exceptions being thrown from functions.
Problem:
Incorrect handling of exceptions often leads to memory leaks, undefined behavior, or application crashes. If throwing exceptions from constructors, destructors, or while working with resources is not taken into account, it leads to serious issues with the program's state.
Solution:
The basic syntax involves using try-catch. Exceptions can be of any type, but it is recommended to derive custom exceptions from std::exception. The noexcept keyword (C++11+) indicates that a function should not throw exceptions; throwing an exception from a noexcept function calls std::terminate().
Code example:
#include <iostream> #include <stdexcept> void func() noexcept(false) { throw std::runtime_error("Error!"); } int main() { try { func(); } catch(const std::exception& ex) { std::cout << ex.what(); } }
Key features:
Is it acceptable to throw exceptions in destructors?
No, throwing an exception from a destructor during stack unwinding leads to std::terminate(). Exceptions in destructors should be caught within the destructor itself.
What happens if you throw an exception from a noexcept function?
std::terminate will be called, and the program will terminate abnormally. noexcept is a strict contract.
Can exceptions be caught by value? Why is this dangerous?
Catching by value is possible, but the object will be copied (object slicing). It is recommended to use const &.
Code example:
try { throw std::out_of_range("err"); } catch (const std::exception& e) { /* ... */ }
The code was throwing exceptions in resource destructors; upon abnormal termination, the stack was unwound improperly, leaving resources as leaks.
Pros:
Cons:
Critical methods were marked noexcept, destructors handled all exceptions internally. Catches by reference were used, and all errors were logged.
Pros:
Cons: