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.