C: Simple Defer, Ready to Use
A proposal to add a `defer`-style cleanup mechanism to C, inspired by Go and long emulated via GCC extensions and macros, is reigniting debate over how the language should handle resource management. Supporters argue that built-in defer or cleanup attributes would prevent common bugs around leaks and error paths, offering a safer alternative to manual gotos and ad‑hoc patterns used in large C codebases like the Linux kernel. Critics counter that such features obscure control flow, risk subtle ordering bugs, and further erode C’s supposed simplicity, suggesting that more feature-rich languages or explicit cleanup code remain preferable.
Role and Value of defer in C
- Many see a standardized
deferas long overdue for C, arguing it would prevent resource leaks and common cleanup bugs, especially for programmers used to C++ RAII. - Others say C does not “need” this; existing patterns (gotos, arrow pattern, explicit cleanup blocks) are sufficient and more explicit.
- Some argue a mature language must grow to address real-world pain points; others fear feature bloat and want C to remain minimal and low-level.
Existing Mechanisms and Implementations
- GCC’s
__attribute__((cleanup))already provides scope-exit cleanup; Apple’s libc and the Linux kernel use similar patterns. - The showcased macro implementation uses GCC nested functions; discussion clarifies:
- Trampolines (and executable stacks) appear only when nested functions escape via pointers.
- In the presented usage, no executable stack is needed and calls are optimizable.
- Clang lacks GCC-style nested functions; alternate approaches include Blocks,
cleanupattributes, or custom macros. - In C++, scope guards (e.g., Folly, Boost.Scope, homegrown
ScopeGuard/lambda patterns) already provide defer-like behavior.
Goto, Structured Programming, and Readability
- Several commenters defend
gotofor structured error handling and breaking out of nested loops, citing the Linux kernel as a positive example. - Others remain wary, viewing
gotoas a marker of messy code; alternatives likedo { … } while (0)or one-iteration loops withbreakare used instead. - There’s an extended debate on Dijkstra’s critique:
- One side claims modern
gotois heavily “tamed” compared to what he attacked. - Another counters that C/C++
gotostill breaks structured reasoning and can create irreducible control flow.
- One side claims modern
Visibility vs. Hidden Control Flow
- Pro-
defercamp: less boilerplate, fewer missed cleanups, clearer intent (“do X, and when leaving, do Y”). - Skeptics:
defer(and C++ destructors) introduce invisible jumps and non-obvious execution order, especially with nested defers; they prefer explicit error paths with clearly ordered teardown. - Some suggest tooling that “desugars”
deferto explicit gotos as a compromise between high-level clarity and low-level inspectability.
Exceptions and Unwinding Interactions
- C standard does not define interaction with C++ exceptions; behavior is compiler- and flag-dependent.
- GCC’s
cleanupcan participate in stack unwinding when-fexceptionsis enabled, but this is non-default and not universal. - Consensus: interaction with exceptions is important in mixed C/C++ code but currently unclear for a standardized
defer.