Skip to content

cpp exception

serhij.zolotukhin edited this page May 10, 2026 · 27 revisions

C++ language

Exception Safety Guarantees

These guarantees are a contract between the function and its caller, ensuring the program remains predictable and manageable even during errors. This concept is language-independent.

https://rollbar.com/blog/error-exceptions-in-c/ https://medium.com/@dnotitia/back-to-basics-error-handling-in-c-4afb20b5f98b https://www.damonyuan.com/tech/260303-strong-exception-safty https://www.opensourceforu.com/2011/06/joy-of-programming-levels-of-exception-safety/ https://towardsdev.com/cpp-exception-safety-strong-basic-guarantees-0e04901bd9bd

  • No Guarantee - An exception may leak resources or leave objects in an invalid state.
  • Basic guarantee - No resource leaks, invariants are preserved, but object value may change.
  • Strong guarantee - Operation is transactional: either full success or no visible effect.
  • No-throw guarantee - Operation never lets exceptions escape.

The classic strong-guarantee technique: copy-and-swap

Copy-and-swap is just one instance of a broader principle: do anything that can throw first, then commit with operations that can’t. The Two-Phase Pattern: Risky Work First, Commit Last

Throwing Exceptions in C++: By Value or By Pointer

https://medium.com/@bsharmarishab/throwing-exceptions-in-c-by-value-or-by-pointer-014361231e40

  • Throwing by Value: The Recommended Approach The C++ community has largely settled on throwing by value because:
  • It eliminates memory management headaches
  • It follows RAII (Resource Acquisition Is Initialization) principles
  • It’s consistent with how most C++ objects are passed around
  • It’s less prone to errors and leaks
  • Throwing by Pointer: The Problematic Approach A pointer-based exception handling is dangerous and prone to memory leaks or crashes.

Catch by Value or Reference

https://www.geeksforgeeks.org/cpp/exception-handling-c/ the catch block can catch exceptions either by value or by reference

  • Catch by Value: Catching exceptions by value creates a new copy of the thrown object in the catch block.
  • Catch by Reference: Catch by reference method just pass the reference to the exception thrown instead of creating a copy. The main advantage of this method is in catching polymorphic exception types.

Handle Uncaught Exceptions

If the exception is not caught by any of the catch block (in case catch all is not present), then by default, the exception handling subsystem aborts the execution of the program.

Exception Propagation

In C++, exception propagation is the process where an unhandled exception "bubbles up" the call stack from the function where it was thrown toward the main() function.

Deriving from std::exception

All exceptions generated by the standard library inherit from std::exception. https://en.cppreference.com/cpp/error/exception

Stack Unwinding

Stack unwinding is the process of removing function call frames from the call stack at runtime. During this process, local objects are destroyed in the reverse order of their creation. https://medium.com/@sireeshac/stack-unwinding-during-exception-handling-in-c-c814c5ddfbe0 https://www.geeksforgeeks.org/cpp/stack-unwinding-in-c/ https://research.cs.queensu.ca/home/stephan/elec377/tut5/stack.html

Stack is comprised of stack frames. Each stack frame corresponds to one function call

Frame pointer(stored in bp register on x86) points to the beginning of the stack frame and stack pointer(stored in sp register on x86) points to the top of the stack

noexcept

In C++, noexcept is a keyword used to specify whether a function is guaranteed not to throw exceptions. https://www.geeksforgeeks.org/cpp/noexcept-specifier-in-cpp-17/

If a function marked noexcept does throw an exception that escapes its scope, the program immediately calls std::terminate() and aborts.

Since C++11, destructors and certain special member functions (like deallocation functions) are implicitly noexcept unless explicitly marked otherwise.

  • The noexcept Specifier
  • The noexcept Operator

Why Use noexcept

  • Move Semantics Optimization: This is the most critical use case. Containers like std::vector will only use an object's move constructor during reallocation if it is marked noexcept. If it might throw, the vector will use the slower copy constructor instead to maintain strong exception safety.
  • Compiler Hints: It informs the compiler that it doesn't need to generate complex stack-unwinding code for that function, leading to smaller and potentially faster binaries.
  • Documentation

Catching All Exceptions in C++

To catch all kinds of exceptions in our catch block in C++, we can define the catch block using the catch-all clause - catch (...), https://www.geeksforgeeks.org/cpp/how-to-catch-all-exceptions-in-cpp/

Best Practices

https://medium.com/@bsharmarishab/throwing-exceptions-in-c-by-value-or-by-pointer-014361231e40 https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#e-error-handling https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#e14-use-purpose-designed-user-defined-types-as-exceptions-not-built-in-types

Always throw by value: It’s simpler, safer, and follows the principle of least surprise. Catch by const reference: This avoids unnecessary copies while maintaining safety. Make your exception objects copyable: Since they’ll be copied during the throw process. Keep exception objects small: Large exception objects could impact performance during the copy operation.

C++ Core Guidelines -> E: Error handling

  • E.14: Use purpose-designed user-defined types as exceptions (not built-in types)
  • Deriving from std::exception gives the flexibility to catch the specific exception or handle generally through std::exception:

optional topics

open questions

  • void f() throw () - depricated

  • re throw - create a new instace of execption - when an instance is created and deleted

  • are we handling an exception for now

  • where we store exception object and how we pass it when Stack Unwinding happens. - we store in a heap

  • try for whole function body void f() try { } catch () { }

  • exception class - copy / move constructor, copy-elision https://medium.com/@tusharmalhotra_81114/copy-elision-in-c-a-simple-way-to-optimize-your-code-be33f492920e

  • bad pratices with excetion

  • Multithreading exception

URLs

https://www.geeksforgeeks.org/cpp/exception-handling-c/ https://devabdilah.medium.com/exception-handling-in-c-1ba1dadae4f9 https://www.linkedin.com/pulse/exception-handling-c-how-works-under-hood-compilers-sona-badalyan-9co6e/ https://akrzemi1.wordpress.com/2011/09/21/destructors-that-throw/ https://www.sandordargo.com/blog/2020/07/22/always-catch-exceptions-by-reference https://gist.github.com/MangaD/8c22b388733b2d0b734969e58c94f58c

https://www.youtube.com/watch?v=zBskaBF-Wxo&list=PLaSMZtEVIQLfkQ5rV839mtFUXXNTgiGAx&index=4

TODO - Constructor / destructor exception handling

https://isocpp.org/wiki/faq/exceptions#ctors-can-throw https://rollbar.com/blog/throw-exceptions-in-cpp-constructors/ https://medium.com/cpp-station/exception-handling-in-constructors-26bf4c811b46 RAII principle ??? If a destructor throws during stack unwinding (while searching for a handler for another exception), your program will terminate.

TODO - Standard Library Exception Hierarchy

https://flylib.com/books/en/2.253.1/standard_library_exception_hierarchy.html https://www.tutorialspoint.com/cplusplus/cpp_exceptions_handling.htm

exception

  • logic_error

    • domain_error
    • invalid_argument
    • length_error
    • out_of_range
  • runtime_error

    • range_error
    • overflow_error
    • underflow_error
  • bad_alloc

  • bad_cast

  • bad_typeid

  • bad_exception

My side bar

Clone this wiki locally