The exception handling system in C++ is based on the try-catch mechanism and the throw keyword. When an exceptional situation occurs (for example, a resource error, or an invariant violation), an exception is raised inside the try block through the throw operator. The process of searching for a suitable handler (catch) is done by unwinding the stack until the first matching type is found.
Important details:
std::exception).noexcept specifier.Designing:
catch(const std::exception& e).Code Example:
#include <iostream> #include <stdexcept> void mayFail(bool fail) { if (fail) throw std::runtime_error("Process error"); } int main() { try { mayFail(true); } catch (const std::exception& ex) { std::cout << "Caught exception: " << ex.what() << std::endl; } }
What happens if an exception is thrown from a destructor while another exception is being propagated up the stack?
Answer: The program will terminate abnormally by calling std::terminate() because during exception handling, generating a new exception (double exception) is not allowed, otherwise stack unwinding is disrupted.
Example:
struct CrashOnDestruct { ~CrashOnDestruct() noexcept(false) { throw std::runtime_error("Error in destructor!"); } }; void func() { CrashOnDestruct obj; throw std::logic_error("Error handling"); } int main() { try { func(); } catch (...) { } } // Will terminate via std::terminate()
Story
In a large financial application, exceptions were thrown from the destructor of a wrapper class over the database. One of the cornerstone transactions, upon encountering an error, initiated an exception, and during unwind exit, the destructor was called, which also threw an error. The entire application crashed, losing user work. Developers had to urgently replace throw in destructors with logging and proper handling.
Story
A microservice handled exceptions by type: catch(std::exception). One of the threads threw exceptions of user-defined types (not derived from std::exception). Such errors were not caught, leading to unexpected connection drops and memory leaks.
Story
The absence of the noexcept specifier in move methods of containers resulted in the standard library using a slow copy instead of a fast move operation; a significant performance drop was detected only during load testing.