A production bug that made me care about undefined behavior

Nature of the bug: uninitialized vs “true” UB

  • Many commenters say this is fundamentally an “uninitialized variable / garbage value” bug, not the more exotic “nasal demons” kind of undefined behavior.
  • Others point out that in standard C/C++, reading uninitialized data is UB, and that the “could be anything” outcome is a direct consequence of that.
  • Several stress that even if the standard had defined “indeterminate but stable garbage,” the logical bug (assuming a default value) would still exist.

Default initialization and language design

  • Strong support for “initialize everything explicitly,” especially for fundamental types.
  • Several argue modern languages should (and mostly do) zero‑initialize by default, with an explicit “uninitialized” escape hatch for performance‑critical cases.
  • Counterpoint: zero‑init as default can be wrong if all‑zero is not a valid value; some prefer languages that force explicit initialization or a Default/MaybeUninit-style mechanism (as in Rust).
  • Some wish C++ had inverted defaults: everything initialized unless explicitly marked no_init / uninitialized.

C++26 and “erroneous behavior”

  • One thread explains that C++26 will treat reading uninitialized variables as “erroneous behavior” rather than UB: compilers are encouraged to diagnose and may assign arbitrary but well‑specified “some value.”
  • There is debate over whether this meaningfully restricts optimizations or just formalizes current practice; some find the distinction from UB unclear and possibly toothless.

Compiler optimizations under UB

  • Multiple godbolt examples show surprising codegen:
    • Partially initialized structs being returned as if both branches executed.
    • Functions effectively deleting or skipping code after a UB point.
    • Values acting “paradoxically” (different effective values at different uses).
  • Some defend this as legitimate: if you leave a value uninitialized, you said “any value is fine,” so the optimizer can pick whatever is convenient.
  • Others argue this is “technically correct but practically harmful” and that compilers should treat such values as opaque, not fold them into constants.

Practical advice and structural issues

  • Common recommendations:
    • Always give struct fields explicit defaults.
    • Use sanitizers / runtime checks (including stack poisoning options) to catch uninitialized reads.
    • Avoid patterns where structs flip between POD and non‑POD, which can silently change initialization rules.
  • Some note the logical design is also flawed: two booleans success/error encode impossible combinations; a single status or richer enum / timestamp would be more robust.