• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1+++
2title = "Exceptions"
3description = "Exceptions with their good and bad sides."
4weight = 10
5+++
6
7
8Exceptions are the default mechanism in C++ for reporting, propagating and
9processing the information about function failures. Their main advantage is
10the ability to describe the "success dependency" between functions: if you want to
11say that calling function `g()` depends on the successful execution of function `f()`,
12you just put `g()` below `f()` and that's it:
13
14```c++
15int a()
16{
17  f();
18  g();        // don't call g() and further if f() fails
19  return h(); // don't call h() if g() fails
20}
21```
22
23In the C++ Standard terms this means that `f()` is *sequenced before* `g()`.
24This makes failure handling extremely easy: in a lot of cases you do not have
25to do anything.
26
27Also, while next operations are being canceled, the exception object containing
28the information about the initial failure is kept on the side. When at some point
29the cancellation cascade is stopped by an exception handler, the exception object
30can be inspected. It can contain arbitrarily big amount of data about the failure
31reason, including the entire call stack.
32
33
34### Downsides
35
36There are two kinds of overheads caused by the exception handling mechanism. The
37first is connected with storing the exceptions on the side. Stack unwinding works
38independently in each thread of execution; each thread can be potentially handling
39a number of exceptions (even though only one exception can be active in one thread).
40This requires being prepared for storing an arbitrary number of exceptions of arbitrary
41types per thread. Additional things like jump tables also need to be stored in the
42program binaries.
43
44Second overhead is experienced when throwing an exception and trying to find the
45handler. Since nearly any function can throw an exception of any time, this is
46a dynamic memory allocation. The type of an exception is erased and a run-time type
47identification (RTTI) is required to asses the type of the active exception object.
48The worst case time required for matching exceptions against handlers cannot be easily
49predicted and therefore exceptions are not suitable for real-time or low-latency
50systems.
51
52Another problem connected with exceptions is that while they are good for program
53flows with linear "success dependency", they become inconvenient in situations where
54this success dependency does not occur. One such notable example is releasing acquired
55resources which needs to be performed even if previous operations have failed.
56Another example is when some function `c()` depends on the success of at least one
57of two functions `a()` and `b()` (which try, for instance, to store user data by
58two different means), another example is when implementing a strong exception safety
59guarantee we may need to apply some fallback actions when previous operations have
60failed. When failures are reported by exceptions, the semantics of canceling all
61subsequent operations is a hindrance rather than help; these situations require special
62and non-trivial idioms to be employed.
63
64For these reasons in some projects using exceptions is forbidden. Compilers offer
65switches to disable exceptions altogether (they refuse to compile a `throw`, and turn
66already compiled `throw`s into calls to `std::abort()`).
67