Cool project! I take it the goal is that, overhead being acceptable, most C / C++ programmes don't actually "have to be" rewritten in something like Rust? I wonder how / where Epic Games comes in?
Notes by djb on using Fil-C
191–200 of 263 posts
Re: Notes by djb on using Fil-C
#192Earlier quoted context omitted.
It's super fun to write C and C++ code in Fil-C because it's like this otherworldly crossover between Java and C/C++: - Unlike Java, you get fantastic startup times. - Unlike Java, you get access to actual syscall APIs. - Unlike Java, you can leverage the ecosystem of C/C++ libraries without having to write JNI wrappers (though you do have to be able to compile those libraries with Fil-C). - Like Java, you can just `…
> Like Java, you can just `new` or `malloc` without `delete`ing or `free`ing. Is your intention that people use the Fil-C garbage collector instead of free()? Or is it just a backstop in case of memory leak bugs? Can the GC be configured to warn or panic if something is GCed without free()? Then you could detect memory leak bugs by recompiling with Fil-C - with less overhead than valgrind, although I’m guessing still…
Wow great question!
My intention is to give folks powerful options. You can choose:
- Compile your code with Fil-C while still maintaining it for Yolo-C. In that case, you'll be calling free(). Fil-C's free() behavior ensures no GC-induced leaks (more on that below) so code that does this will not have leaks in Fil-C.
- Fully adopt Fil-C and don't look back. In that case, you'll probably just lean on the GC. You can still fight GC-induced leaks by selectively free()ing stuff.
- Both of the above, with `#ifdef __FILC__` guards to select what you do. I think you will want to do that if your C program has a custom GC (this is exactly what I did with emacs - I replaced its super awesome GC with calls to my GC) or if you're doing custom arena allocations (arenas work fine in Fil-C, but you get more security benefit, and better memory usage, if you just replace the arena with relying on GC).
The reason why the GC is there is not as a backstop against memory leaks, but because it lets me support free() in a totally sound way with deterministic panic on any use-after-free. Additionally, the way that the GC works means that a program that free()s memory is immune to GC-induced memory leaks.
What is a GC-induced leak? For decades now, GC implementers like me have noticed the following phenomena:
- Someone takes a program that uses manual memory management and has no known leaks or crashes in some set of tests, and converts it to use GC. The result is a program that leaks on that set of tests! I think Boehm noticed this when evangelizing his GC. I've noticed it in manual conversions of C++ code to Java. I've heard others mention it in GC circles.
- Someone writes a program in a GC'd language. Their top perf bug is memory leaks, and they're bad. You scratch your head and wonder: wasn't the whole point of GC to avoid this?
Here's why both phenomena happen: folks have a tendency keep dangling pointers to objects that they are no longer using. Here's an evil example I once found: there's a Window god-object that gets created for every window that gets opened. And for reasons, the Window has a previousWindow pointer to the Window from which the user initiated opening the window. The previousWindow pointer is used in initialization of the Window, but never again. Nobody nulled previousWindow.
The result? A GC-induced leak!
In a malloc/free program, the call to previousWindow.destroy() (or whatever) would also delete (free()) the object, and you'd have a dangling pointer. But it's fine because nobody dereferences it. It's a correct case of dangling pointers! But in the GC'd program, the dangling program keeps previousWindow around, and then there's previousWindow.previousWindow, and previousWindow.previousWindow.previousWindow, and... you get the idea.
This is why Fil-C's answer to free() isn't to just ignore it. Fil-C strongly supports free():
- Freeing an object immediately flags the capability as being empty and free. No memory accesses will succeed on the object anymore.
- The GC does not scan any outgoing references from freed objects (and it doesn't have to because the program can't access those references). Note that there's almost a race here, except https://fil-c.org/safepoints saves us. This prevents previousWindow.previousWindow from leaking.
- For those pointers in the heap that the GC can mutate, the GC repoints the capability to the free'd singleton instead of marking the freed object. If all outstanding pointers to a freed object are repointable, then the object won't get marked, and will die. This prevents previousWindow from leaking.
> Can the GC be configured to warn or panic if something is GCed without free()?
Nope. Reason: the Fil-C runtime itself now relies on GC, and there's some functionality that only a GC can provide that has proven indispensable for porting some complex stuff (like CPython and Perl5).
It would take a lot of work to convert the Fil-C runtime to not rely on GC. It's just too darn convenient to do nasty runtime stuff (like thread management and signal handling) by leaning on the fact that the GC prevents stuff like ABA problems. And if you did make the runtime not rely on GC, then your leak detector would go haywire in a lot of interesting ports (like CPython).
But, I think someone might end up doing this exercise eventually, because if you did it, then you could just as well build a version of Fil-C that has no GC at all but relies on the memory safety of sufficiently-segregated heaps.
Re: Notes by djb on using Fil-C
#193Related: Fil-C: A memory-safe C implementation - https://news.ycombinator.com/item?id=45735877 - Oct 2025 (130 comments) Safepoints and Fil-C - https://news.ycombinator.com/item?id=45258029 - Sept 2025 (44 comments) Fil's Unbelievable Garbage Collector - https://news.ycombinator.com/item?id=45133938 - Sept 2025 (281 comments) InvisiCaps: The Fil-C capability model - https://news.ycombinator.com/item?id=45123672 - Sep…
Re: Notes by djb on using Fil-C
#194Re: Notes by djb on using Fil-C
#195Is there a reason that some of the linked benchmarks, if I'm reading it right, have Fil-C running faster than C?[0] I assume it's just due to micro-benchmark variability but I'm curious. Some of them seem impossibly fast compared to C so I wonder if there are some correctness issue there. [0] https://cr.yp.to/2025/20251028-filcc-vs-clang.html
Re: Notes by djb on using Fil-C
#196Re: Notes by djb on using Fil-C
#197Is there a reason that some of the linked benchmarks, if I'm reading it right, have Fil-C running faster than C?[0] I assume it's just due to micro-benchmark variability but I'm curious. Some of them seem impossibly fast compared to C so I wonder if there are some correctness issue there. [0] https://cr.yp.to/2025/20251028-filcc-vs-clang.html
Usually garbage collection does improve alot of benchmarks, just look at the hans boem gc benchmarks.
Re: Notes by djb on using Fil-C
#198Earlier quoted context omitted.
Usually garbage collection does improve alot of benchmarks, just look at the hans boem gc benchmarks.
Back in the day, the cheat was to set up the GC so that the GC happened outside the timed portion of the benchmark. You know what's faster than the fastest GC? Not doing it.
Re: Notes by djb on using Fil-C
#199Earlier quoted context omitted.
I think that's the build of LLVM+Clang itself.
Yes, linking LLVM takes up a lot of memory. The documented guidance is to allow one link job per 15 GB of RAM [1]. [1] https://llvm.org/docs/CMake.html#frequently-used-llvm-relate...
Re: Notes by djb on using Fil-C
#200Can a program be written only partially in Fil-C? That is to say, can we link regular C and Fil+C object files in a single executable?
(worth reading, i think all the stuff Fil writes is both super informative & quite entertaining.)