Printf debugging is ok

Overall stance on printf vs debuggers

  • Many see printf/log debugging and interactive debuggers as complementary tools; “use whatever works.”
  • Some argue debuggers should be the first tool, with printf/logging secondary.
  • Others find debuggers rarely necessary or too mentally costly, preferring prints plus fast test loops.
  • A minority claim heavy reliance on printf is a symptom of poor tooling and culture, not a virtue.

Educational and code-understanding value of debuggers

  • Visual debuggers are praised as teaching tools: they help learners see call stacks, control flow, closures, and data as it moves.
  • Debuggers are also used to understand unfamiliar, complex codebases by inspecting call stacks and caller data without editing code.

Contexts where printf/logging shine

  • Embedded, kernel, firmware, safety‑critical, and hardware-interfacing code often cannot tolerate breakpoints or pausing; printf/LEDs/logging are sometimes all that works.
  • Distributed systems, network services, intermittent failures, and long-running jobs often rely on logging/traces or large dumps (JSON, binary traces) instead of interactive stepping.
  • Some environments (CLI tools, multi-team services, cloud setups) make attaching debuggers or configuring them awkward, so temporary prints are pragmatically preferred.

Logging, observability, and tooling

  • Distinction is drawn between ad‑hoc “printf debugging” and structured, levelled logging designed for long-term observability.
  • People highlight benefits of centralized logging (Elastic/Kibana, Datadog, etc.), tracepoints/logpoints, snapshot/time-travel debuggers, and record‑and‑replay tools.
  • There is frustration with poor debugger UX (e.g., VS Code launch configs, weak CLIs) vs highly praised IDE debuggers.
  • Fast, optimized debug builds (e.g., using -Og with debug info) are recommended; overloaded “debug” builds with heavy self-checks can become uselessly slow.

Risks, heisenbugs, and safety

  • Printf can change behavior: stack layout, caching, timing, and hardware status reads, sometimes “fixing” or hiding bugs.
  • Low-level anecdotes: uninitialized variables, out-of-bounds writes, race conditions, and shared buffers becoming visible or invisible depending on prints/optimizations.
  • Leaving debug prints in production can leak sensitive data; recent incidents are cited, and linters/filters are suggested to prevent this.

Meta-points and debugging style

  • Several stress avoiding false dichotomies and adversarial framing; present options and let engineers choose.
  • Some advocate asserts, contracts, and tests as primary defenses, with printf and debuggers as secondary tools.