Error Handling and Exceptions
Team LiB
Previous Section Next Section

Error Handling and Exceptions

68. Assert liberally to document internal assumptions and invariants.

Be assertive! Use assert or an equivalent liberally to document assumptions internal to a module (i.e., where the caller and callee are maintained by the same person or team) that must always be true and otherwise represent programming errors (e.g., violations of a function's postconditions detected by the caller of the function). (See alsoItem 70.) Ensure that assertions don't perform side effects.

69. Establish a rational error handling policy, and follow it strictly.

Consciously specify, and conscientiously apply, what so many projects leave to ad-hoc (mis)judgment: Develop a practical, consistent, and rational error handling policy early in design, and then stick to it. Ensure that it includes:

  • Identification: What conditions are errors.

  • Severity: How important or urgent each error is.

  • Detection: Which code is responsible for detecting the error.

  • Propagation: What mechanisms are used to report and propagate error notifications in each module.

  • Handling: What code is responsible for doing something about the error.

  • Reporting: How the error will be logged or users notified.

Change error handling mechanisms only on module boundaries.

70. Distinguish between errors and non-errors.

A breach of contract is an error: A function is a unit of work. Thus, failures should be viewed as errors or otherwise based on their impact on functions. Within a function f, a failure is an error if and only if it violates one of f's preconditions or prevents f from meeting any of its callees' preconditions, achieving any of f's own postconditions, or reestablishing any invariant that f shares responsibility for maintaining.

In particular, here we exclude internal programming errors (i.e., where the caller and callee are the responsibility of the same person or team, such as inside a module), which are a separate category normally dealt with using assertions (see Item 68).

71. Design and write error-safe code.

Promise, but don't punish: In each function, give the strongest safety guarantee that won't penalize callers who don't need it. Always give at least the basic guarantee.

Ensure that errors always leave your program in a valid state. This is the basic guarantee. Beware of invariant-destroying errors (including but not limited to leaks), which are just plain bugs.

Prefer to additionally guarantee that the final state is either the original state (if there was an error the operation was rolled back) or the intended target state (if there was no error the operation was committed). This is the strong guarantee.

Prefer to additionally guarantee that the operation can never fail at all. Although this is not possible for most functions, it is required for functions like destructors and deallocation functions. This is the no-fail guarantee.

72. Prefer to use exceptions to report errors.

When harmed, take exception: Prefer using exceptions over error codes to report errors. Use status codes (e.g., return codes, errno) for errors when exceptions cannot be used (see Item 62), and for conditions that are not errors. Use other methods, such as graceful or ungraceful termination, when recovery is impossible or not required.

73. Throw by value, catch by reference.

Learn to catch properly: Throw exceptions by value (not pointer) and catch them by reference (usually to const). This is the combination that meshes best with exception semantics. When rethrowing the same exception, prefer just throw; to throw e;.

74. Report, handle, and translate errors appropriately.

Know when to say when: Report errors at the point they are detected and identified as errors. Handle or translate each error at the nearest level that can do it correctly.

75. Avoid exception specifications.

Take exception to these specifications: Don't write exception specifications on your functions unless you're forced to (because other code you can't change has already introduced them; see Exceptions.)

    Team LiB
    Previous Section Next Section