Fil-C: Garbage In, Memory Safety Out [video]
Fil-C, a memory-safe C implementation that enforces safety at runtime, is being evaluated as an alternative or complement to Rust’s primarily compile-time safety model. Commenters debate how far Fil-C’s guarantees extend—especially around syscalls, data races, and mmap—versus what Rust and other languages (Go, C#, TypeScript, Python) already offer through safe wrappers, runtimes, and tooling. Many see Fil-C’s main value in hardening large existing C/C++ codebases with relatively few changes, while questioning its performance overhead, suitability for new projects, and the promotional framing that sometimes positions it as categorically “safer” than Rust.
Fil-C vs. Rust: Safety Model
- Fil-C and Rust are framed as distinct approaches: Rust emphasizes compile‑time prevention of undefined behavior; Fil-C emphasizes making undefined behavior impossible at runtime.
- Some argue Rust “prefers” static checking but still relies on runtime checks (bounds checks, overflow in debug, RefCell, etc.), so claims that it prevents all undefined behavior statically are challenged.
- Several comments note the approaches are complementary: Fil-C‑style runtime checks could be wrapped around Rust unsafe code, yielding “safety in depth.”
Syscalls, mmap, and Runtime Architecture
- Fil-C’s “user libc” calls into a Fil-C runtime that filters syscalls, which then go through a lower‑level libc. The claim: Fil-C programs are memory safe down to syscalls, and syscalls cannot escape protections (barring /proc‑style tricks).
- A key example is
mmap: Fil-C exposes an API with many mmap capabilities while guaranteeing memory safety; Rust’s safe subset cannot offer equivalent guarantees, and mmap use is typically unsafe. - Critics respond that Rust can have safe syscall wrappers too, and that both systems ultimately rely on some unsafe layer.
Unsafe Code and Trust Boundaries
- In Rust, unsafe code can appear in user code and dependencies; the trust boundary is user‑controlled (and can be tightened with
forbid(unsafe_code)and tooling). - In Fil-C, regular programs have no unsafe blocks; all unsafe behavior is confined to the compiler/runtime. Some see this centralization as strictly safer; others see it as just moving the same risk.
Data Races and Limits of Safety
- Fil-C is described as preserving memory safety even under data races; critics argue there are race scenarios where safety properties degrade (e.g., accessing a different object via a racy pointer).
- Commenters stress that kernel and hardware bugs, /proc tricks, ptrace, process_vm_writev, and similar mechanisms remain outside any userspace memory safety guarantee.
Performance, Use Cases, and Comparisons
- Fil-C adds runtime overhead (roughly likened to “2x slower, 4x memory” in one comment), making it unsuitable for some contexts (e.g., kernels, some embedded).
- Many see the main value in hardening large existing C/C++ codebases with minimal changes; some think it can also be fast enough for production in parts of userspace.
- For greenfield development, skeptics question choosing Fil-C over mature GC languages (Go, C#, TypeScript, Python) that already provide memory safety and richer ecosystems.
Community and Rhetoric
- Multiple comments note recurring “us vs. them” framing in Fil-C discussions, especially versus Rust, and express concern about overstated or absolute claims (e.g., around data‑race safety).
- Others argue that detailed, even adversarial, comparisons help clarify trade‑offs and improve shared understanding.