Chapter 13 — Teaching Notes

One-line purpose. Turn optimistic code into robust code: ask whether each operation worked, halt deliberately when it did not, arm the compiler to catch what you missed, and check your own beliefs — the one Part II topic no track should skip.

Key ideas to emphasize

  • One pattern, many places. iostat (I/O), stat (allocation), and coarray stat= are the same idea — ask, then decide. Teach the shape once and students recognize it everywhere. This is the spine of §13.1.
  • The exit code is a promise to the shell. Students think a program ends when it prints; it actually ends by reporting an integer that automation reads. error stop with a chosen code is how you tell the truth about failure. The echo $? demo makes this concrete and lands hard.
  • Make the silent failure loud. The chapter's method (Case Study 1) is the transferable skill: reproduce, -ffpe-trap to make it loud, read the backtrace, gdb to inspect, then fix + guard. Walk it live.
  • An assertion is an executable belief. The distinction that matters: stat/iostat handle what the world does to you (expected); assertions catch what you got wrong (the "impossible"). Do not let students use assertions for expected errors or status returns for logic bugs.
  • Implicit save is the trap they will actually hit. integer :: n = 0 in a procedure is saved, not reset. Demo the 1,2,3-vs-1,1,1 counter; it is memorable and genuinely surprising.

Misconceptions to preempt

  • "Fortran zeroes my locals." (No — uninitialized locals hold garbage; often zero by luck, hence platform-dependent bugs.)
  • "error stop and stop are the same." (Different termination kind and exit code; different parallel semantics.)
  • "== on reals is fine if the values 'should' be equal." (Almost never true for computed reals; use a tolerance.)
  • "-fcheck=all should be on in production." (No — it costs speed; strip it for the production run, keep the cheaper -fbacktrace/-ffpe-trap.)
  • "A NaN in the output means the physics is unstable." (Often it is a mundane unset/unvalidated value — Case Study 1's whole point.)
  • "Trap all FP exceptions." (Never underflow/inexact — they fire in correct code.)

A live demonstration (8 minutes)

  1. Compile the bounds_demo (§13.3) plainly and run — it prints something plausible. Then recompile with -fcheck=all -g — a runtime error with a line number. The gap is the lesson.
  2. Compile a two-line divide-by-zero with and without -ffpe-trap=zero -fbacktrace. Without: prints Inf, continues. With: SIGFPE at the line. (Do not claim exact message text — versions differ; the behavior is the point.)
  3. Run the implicit-save counter (example-03) and let the 1,2,3 output surprise them before you explain why.

Class-time budget (~50 min)

  • 8 min: errors as values — iostat recap → stat/errmsg (§13.1).
  • 8 min: stop vs error stop, exit codes, echo $? (§13.2).
  • 12 min: the three flags, with the two live demos (§13.3).
  • 6 min: gdb/valgrind — what each is for (§13.4); keep it brief, it is reference material.
  • 10 min: assertions + defensive programming, the executable-belief idea (§13.5).
  • 6 min: the usual suspects, esp. implicit save and integer overflow (§13.6), and the Project Checkpoint.

Prerequisites to review

Ch. 7 (iostat/iomsg, namelist) — this chapter generalizes it; Ch. 5 (arrays, bounds, allocatable); Ch. 9 (field_t); Ch. 11 (dangling pointers, allocatable-vs-pointer) — both spaced-review targets. A quick recap of iso_fortran_env (error_unit, real64, int32/int64) pays off.

Connections

Back: Ch. 3 (integer division), Ch. 7 (iostat), Ch. 11 (dangling). Forward: Ch. 14 (C error conventions — errno/return codes — vs Fortran's model), Ch. 20 (NaN/Inf, ieee_arithmetic), Ch. 24 (CFL blow-up as an error to catch), Ch. 30 (debug vs release flags), Ch. 37 (assertions complement tests). Naming these payoffs now motivates the discipline.