Giving C a superpower: custom header file (safe_c.h)
C vs C++ vs “C with Superpowers”
- Many argue that if you want RAII, vectors, smart pointers, and sum types, you should just use C++ (possibly in a “C-like” style) instead of macro-heavy C.
- Counterpoints:
- C++ is hard to parse and tool for; C stays “hackable” with simpler parsers and tiny compilers (TCC, slimcc, etc.).
- Some embedded vendors still don’t ship usable C++ toolchains; C remains the lowest common denominator.
- Migrating a large legacy C codebase wholesale to C++ is non-trivial.
Portability, Toolchains, and Extensions
- The header relies on GCC/Clang features like
__attribute__((cleanup))/[[gnu::cleanup]]; this excludes MSVC and strict C99/C11 environments. - Clarifications that C23 only standardizes a small set of attributes; cleanup remains a vendor extension.
- Some suggest using C11
threads.h/ atomics instead of POSIX mutexes for better portability.
Value and Limits of the “Safe C” Header
- Supporters: neat toy, shows how far you can push C toward safer patterns (RAII-like cleanup, vectors, Result types) without adopting full C++/Rust.
- Critics:
- Expect many corner cases and UB; without a spec and battle-hardened implementation it’s risky for serious code.
- Macros create a project-specific mini-language that newcomers must learn.
- Shared-pointer and view/string_view style constructs still allow use-after-free; nothing enforces correct lifetimes or refcount discipline.
- “Result” types don’t force checking like Rust; you can still ignore errors.
Safety vs. Language Choice
- Some say energy should go into incrementally rewriting C systems in memory-safe languages (Rust, Fil-C, etc.), not layering more macro magic.
- Others argue there are billions of lines of C that can’t be rewritten soon; incremental tools that reduce footguns are valuable.
- Debate over whether an “improved C” could achieve memory safety via ownership and lifetimes without GC; lifetimes + polymorphism seen as likely required.
GC, Fil-C, and Performance
- Fil-C (a GC-backed C runtime) is raised as a more thorough safety approach.
- Long subthread on garbage collection:
- One side: GC overhead is negligible for most programs; safety payoff is huge.
- Other side: GC can significantly hurt throughput, latency, and working set for systems/embedded workloads; manual or ownership-based schemes are still preferred there.
Coding Practices and Alternatives
- Some prefer classic patterns:
goto outcleanup blocks, arenas, or simply not freeing process-lifetime data (like parsed CLI options). - Concern that trying to make C “safe” hides its nature; better to use languages like Nim, Go, Rust, or specialized verified C dialects (Frama-C, Fil-C) when safety is paramount.