Concepts / Throwing and Catching Exceptions

Throwing and Catching Exceptions

The noexcept keyword declares that a function should never throw an exception.

  • Programming
Interactive lab

Try it: try / except / else / finally

How an exception jumps out of a try block to the first matching except clause, when else runs, and why finally always runs.

How it works

  1. Statements in try run until one raises an exception; the rest of try is skipped.
  2. Python checks the except clauses in order and runs the first one whose type matches.
  3. If nothing was raised, the else block runs instead.
  4. finally runs in every case.

Default run (9 steps): Call safe_divide('4'). … Return 25.0. Output was: Worked: 25.0 / Done.

Simplified: One fixed function; int() and / are modelled exactly (including how Python prints floats), but nothing is executed as Python.

Educational simulation

Loading the simulation…

Why a Function Might Promise Silence

Most functions are written on the assumption that something might go wrong. A function may call other functions, request memory, or read input, and any of those operations can fail. When they do, an exception may be thrown. The normal design of an exception-aware program is to let the exception travel outward until some part of the program is prepared to handle it.

Some functions, however, are meant to do their job without ever raising an exception at all. A function that performs only simple, self-contained work may be one of them. The noexcept keyword exists so that the author of such a function can say so directly in the function's declaration. Instead of hoping that callers will assume the function is safe, the author writes the expectation into the code itself.

The rest of this article follows one scenario closely. Before reading the explanation, you will be asked to predict what happens when a noexcept function fails, and then you will check your prediction against the rules the language follows.

Following One Scenario Step by Step

Consider a function named user() that is declared noexcept. Its author expects it to succeed every time. Inside user(), a helper operation runs, and that helper fails and throws an exception. The main function called user(), and main has a catch block ready to handle failures.

What do you think happens?

The helper inside user() throws an exception. Does main's catch block run, does the program keep going normally, or does something else happen?

  • main's catch block handles the exception and the program continues

  • The exception quietly returns to main as it would for an ordinary function

  • terminate() is called and the program is stopped immediately

Reveal answer
Answer:

terminate() is called and the program is stopped immediately. main's catch block never runs.

The source states that when a noexcept function still throws, the language does not carry the exception out to the caller. Instead, terminate() is called and immediately terminates the program.

main()calls user()user()declared noexcepthelper operationthrowsterminate()program stopscatch block in mainnever reachedExceptionthrown inside user()callscallsthrowsescapes noexcept boundary
When the helper throws inside user(), the exception does not reach main's catch block. Because user() is noexcept, the exception is not carried out to the caller and terminate() ends the program.

Trace the path in the diagram. The exception starts in the helper operation, which is running inside user(). It attempts to leave user(). Because user() is declared noexcept, the exception does not continue upward to main as it would from an ordinary function. The catch block in main sits in the caller, but the language never hands the exception to it. The program is terminated at that point, so the catch block has no chance to run.

The noexcept Declaration as a Statement of Intent

Definition

The noexcept keyword declares that a function should never throw an exception.

The keyword is best understood as a statement of intent that travels with the function. Anyone who reads the declaration learns that the function is expected never to throw. That information matters to the people who call the function and to the people who maintain it, because it tells them what they can assume about the function's behavior.

The important word in the definition is should. The declaration does not make a function unable to throw. It records the author's expectation, and the rest of the program is built on top of that expectation. This is why declaring a function noexcept is a decision about the function's design, not a decoration added at the end.

What Happens When the Promise Breaks

Suppose a function is declared noexcept, but during its execution an exception is still thrown. The language does not quietly carry that exception out to the caller, as it would for an ordinary function. Instead, the standard-library function terminate() is called, and it immediately terminates the program. A broken noexcept promise therefore has a visible and immediate consequence.

Function runsException thrown?Normal returnpromise keptPassed to callerordinary functionDeclared noexcept?terminate() calledpromise brokenProgram endsnoyesnoyes
The decisions that lead from a noexcept function throwing to terminate() ending the program. An ordinary, non-noexcept function would instead pass the exception to its caller.
Worked example

Two versions of user()

The same helper operation fails in two versions of user(). In version A, user() is an ordinary function. In version B, user() is declared noexcept. What happens to the exception in each version?

  1. 1
    Version A: ordinary function

    The exception leaves user() and is carried out to the caller, main. main's catch block has the chance to handle it.

  2. 2
    Version B: noexcept function

    The exception is thrown inside user(), which is declared noexcept. The language does not carry the exception out to main.

  3. 3
    Terminate

    terminate() is called and immediately terminates the program. The catch block in main never runs.

Result

The only difference between the two versions is the declaration, yet the outcome is completely different: one version can be recovered by the caller, the other stops the program.

Choosing Where noexcept Belongs

Because a broken promise stops the program, noexcept should be used only where the function's author has a real basis for expecting no exceptions. Most of the time an author cannot be sure that nothing inside a function will ever fail. The useful habit is to ask, before writing the keyword, what would happen if the function did throw.

QuestionGood noexcept candidatePoor noexcept candidate
What work does it do?Simple, self-contained workCalls other functions whose behavior the author does not control
Can its operations fail?The author is confident no failure can occurMemory requests or input operations that can go wrong
If it throws, should the program recover?No: the author expects the work to succeedYes: the program should be able to recover
What does the keyword say?An accurate description of the expectationA false promise that stops the program when broken

Judging whether a function should carry the noexcept declaration

Mistakes Beginners Make with noexcept

  • Common mistake

    Treating noexcept as protection against failure

    What it looks like

    Marking a function noexcept and assuming that the function can no longer fail.

    Why it fails

    The declaration does not make a function unable to throw. It records an expectation, and the source says the keyword does not shield a program from failure.

    Do this instead

    Use noexcept to document an expectation that the author has good reason to hold, and still make sure the work really is expected to succeed.

  • Common mistake

    Marking a function noexcept because it usually succeeds

    What it looks like

    A function that calls a memory request or reads input is marked noexcept since it works in most test runs.

    Why it fails

    Memory requests and input operations can go wrong, and when they do an exception may be thrown. A promise that holds most of the time is still broken when the failure occurs.

    Do this instead

    Leave the keyword off when the function's work includes operations that can fail, and let exceptions propagate to a caller that can handle them.

  • Common mistake

    Expecting a caller's catch block to handle a noexcept throw

    What it looks like

    Wrapping a call to user() in a try and catch, then assuming the catch will handle any failure inside user().

    Why it fails

    When a noexcept function throws, the exception is not carried out to the caller. terminate() is called instead, so the catch block never runs.

    Do this instead

    Handle expected failures inside the code that can produce them, or remove noexcept from functions where recovery by the caller matters.

Practice: Judging a Function

MEDIUM

A function named user() is declared noexcept. Inside it, a helper operation requests memory and reads a line of input. If the input operation fails and throws an exception, trace what happens to the exception, and state whether the caller's catch block can handle it. Then decide whether the noexcept declaration is an accurate statement of intent for this function.

Hints
  • Start from the rule: when a noexcept function still throws, is the exception carried out to the caller?
  • Look at the kinds of operations the function performs. The source names memory requests and input operations as things that can go wrong.
  • Ask whether the author has a real basis for expecting no exceptions before deciding whether the keyword is accurate.

Key Takeaways from the noexcept Promise

  1. 1
    The noexcept keyword declares that a function should never throw an exception, and it records the author's expectation.
  2. 2
    If a noexcept function still throws, the exception is not carried out to the caller. terminate() is called and immediately terminates the program.
  3. 3
    Because a broken promise stops the program, noexcept should be used only where the author has a real basis for expecting success.
  4. 4
    Before writing the keyword, ask what would happen if the function did throw. If the program should be able to recover, leave noexcept off.

At a glance

  • The noexcept keyword declares that a function should never throw an exception, and it is the author's responsibility to make that true.
  • When an exception escapes a noexcept function, it is not carried out to the caller; terminate() is called and the program stops immediately.
  • A caller's catch block cannot rescue a broken noexcept promise, because the exception never reaches the caller.
  • Use noexcept only for functions whose work the author genuinely expects to succeed, and never as protection against failure.

Related concepts

More concepts starting with T