Now as a software developer I feel like this is even more important because I use libraries maintained by thousands of other developers that might also use applications that have these exploits which get their systems compromised pushing malware to thousands of other developers which end up compromising even more libraries.
I believe that memory safety should be the standard for software that thousands if not millions rely on and that it shouldn't be some political issue of X is better, Y is that, Z is something else.
But then again, social engineering is the primary source of malware spread so I don't know.
However, I should probably pipe down, as I would not call myself either one.
Unfortunately, I've never seen a version of this data targeting modern C++ (>=11, with smart pointers, already 15 years old).
When you allocate space with Fil-C's "malloc", some additional bounds checking data precedes the space the program gets to use. Pointers are "fat pointers", with a pointer to the beginning of the buffer and a pointer to someplace within the buffer, allowing ordinary C pointer manipulation.
There's much new verbiage around this. But it's roughly the same idea as GCC "fat pointers".[2][3] So it's not a new idea. It's one that's been tried several times, but never caught on.
There's a performance penalty. Especially if the compiler can't hoist the checks out of loops.
[1] https://fil-c.org/invisicaps
If you want to go deeper, skip the language wars entirely. Tooling does what these languages can't do. I have had great success model checking C with CBMC. Not only does this prevent memory safety issues (including memory leaks), but this also prevents deadlocks. Bonus: you can write user contracts and invariants to verify that every execution path of a function fulfills these contracts and invariants.
Kani comes close with Rust. It doesn't yet have decent concurrency support, but there is nothing that prevents this from being added in the future. The ability to write custom contracts and enforce custom invariants more than makes up for its lack of concurrency support. Similar technology could be used or adapted for Zig or C++.
Use whichever language you like. Just, please look into model checking it. The technology scales just fine, once you get over the learning curve and learn how to use compositional verification.
Depends if I must use programs in the 10%
Assuming I can avoid that 10%, I would choose option [2] and select programs from amongst the 90% with zero issues
The problem I see with option [1] is that there would be no programs to select with zero issues
Over the 40 years I have been using software I have learned I do not need to use "100% of software"
I select a very small percentage of that 100%
I would not want to use most of that "100% of software", for various reasons having nothing to do with memory safety
Coreutils has a good track record. Ffmpeg doesn't. They should have rewritten ffmpeg in Rust, not coreutils.
There are other approaches though like formal verification.
So... Yes, Rust is less safe. Just that now the Rust apologist wants to back away from that and say that actually memory safety isn't actually the end all be all. C has a lot of security problems. Rust has less, at the cost of breaking the ecosystem. Fil-C has even less, and breaks the ecosystem. Why is the place Rust stops now suddenly good enough?
I also feel there's a second dimension to the politics, where Rust is the "woke" language and C / Zig / Odin are now the "anti-woke" languages. At least, going by their most vocal online communities.
I'm sure offline there's still engineering decisions being made (I hope).
Now, maybe I'm only running into these algorithms because these are the problems I'm running into, but in the Rust community I consistently got the message that linked lists were a legacy data structure. In some cases they are, but when they do apply they do so brilliantly.
I know working in Zig leaves plenty of room for memory unsafety. Perhaps that's a bad thing. But I'm implementing an interpreter, and these algorithms are essential for it to run fast. I really do need to be aware of where every allocation happens, and what instructions the computer is running. So for now I stick with Zig, even though I know I'm opening myself up to memory exploits.
Memory safety is a really big reason to use Rust, but it is very very far from the only reason. Even if Fil-C was magically zero-overhead (that is basically what CHERI is), I would still rather use Rust.
Rust has so many advantages over something like Fil-C it's hard to list them. I think Fil-C is a great project but it's only really relevant if you have no choice but to use C. If you can use Rust you also get:
* Compile time memory safety (Fil-C / CHERI are run-time).
* A modern functional-style type system (helps prevent logic bugs).
* Tree ownership (helps prevent logic bugs)
* Sane toolchain (helps prevent hair loss).
* Easy dependencies.
* Vastly more things checked at compile time.
Also I find it amusing how this post claimed it wasn't about Rust and then spent the whole time talking about it.
Rust is great. I don't think that really needs to be debated any more.
Like, of course you can prevent all memory safety errors by using a garbage collector. That has been known since the 90s. In fact, there was a good two decades after Java released where all the research on memory safety just stopped, because the standard answer became "use a GC". If you couldn't use GC, you were stuck with languages made prior to Java - which in practice meant just C - or the one language everyone tried to staple every new programming paradigm onto, C++.
In fact, part of why C++ became such an untameable beast of a language is because it became load-bearing for non-GC projects. Anything not in the ISO C++ standard was, in practice, something you just couldn't do in native code. Oh, of course you can't introspect structs in a compiled language, of course macros are useless and unhygenic, of course templates have to be monomorphized and bloat your binary size. And so the pressure for C++ to be an all-singing, all-dancing, all-dressed language grew.
Rust's big story is memory safety, but the more Rust I wrote, the more I realized that the memory safety is only part of the picture. Rust has a very nicely curated selection of features that allows the language to remain understandable despite the sophistication of the compiler. Memory safety is a selling point, sure, but it is also the lubricant that makes working with those features pleasant.
If you want a real complaint about Rust, it's that some features are oversimplified in ways that make certain scenarios harder and make some features way more "magic" than they should be. Have you ever tried writing Futures code without making use of the async keyword? It's nearly impossible, for several reasons; the main being that Rust's type systems cannot express self-referential borrows. This also makes returning a reference to something in an Rc or RefCell you own more difficult[0]. And there are numerous other states memory can be in that are hidden from Rust's type system. Rust can't even represent a real destructor fn. Dropping a value multiple times, or using it after it's been dropped, is explicitly forbidden; but Drop impls still can't take values out of themselves because Rust doesn't have an "owned reference" - i.e. memory you can take values from but can't deallocate.
But none of this compromises memory safety - it just makes certain things harder than they should be.
[0] Strictly speaking, there's an owning_ref crate that manages this; stdlib is also working on a "mapped mutex guard" type that would do the same thing without a dependency.
Memory safety is just little thing that makes sure that when you write code at 4am that it will not leak memory via trivial mistakes such as forgetting to free something, freeing something twice or passing a freed pointer. I believe AI agents shine here the most because the they do not get tired and are getting pretty damn predictable.
I think the "static analysis" and the "runtime checks" approaches are complementary, not in opposition, making any noise around having to choose one or the other moot.
To apply your logically consistently, you'd also have to throw out Go[1], Java[2], C#[3], and plenty of other languages. I guess you can define a logically consistent taxonomy of languages where Fil-C is the only "safe" language any everything else is unsafe, but then the burden is on you to prove that it's a useful way of thinking about them. Meanwhile, the way that people who consider Go and Java and Rust to be safe and C/C++ to be unsafe will continue to see actual real-world differences in outcomes when using a safe language compared to unsafe ones.
As an aside, it continues to be absolutely wild to me to see how most arguments in favor of C/C++ over Rust nowadays are based on framing things theoretically rather than practical ones. It was not all that long ago that the situation was reversed, with people claiming that Rust's benefits were all theoretical when most C/C++ code would have all of the UB found and removed over time. Now that Rust actually has been getting used for real-world stuff for a few years, and the number of vulnerabilities found in C/C++ code does not seem to be going down any time soon, any actual empirical evidence gets handwaved away. Maybe Fil-C will be able to provide as large benefits to running C safely in production like its proponents claim in the future, and if so, that will be a solid argument against the utility of Rust in a lot of situations, but if we're collectively going to shift the standard to discount pragmatism over theory in this debate, we might as well not try to hide it.
[1]: https://pkg.go.dev/unsafe
[2]: https://docs.oracle.com/cd/E92951_01/coherence/java-referenc...
[3]: https://learn.microsoft.com/en-us/dotnet/api/system.runtime....
I don't mean this to be a gotcha, but I think it's important to say that we can have these in rust too! The only difference is that the first thing we have to talk about is you the user can go about using an intrusive collection correctly. I love the cordyceps crate for this. If you want to be able to use your type as a linked list node, you must implement a Linked trait, the documentation of which clearly explains how to use it safely: https://docs.rs/cordyceps/latest/cordyceps/trait.Linked.html
My system sometimes detects a few bitflips per day.
Also, while such data structures/algorithms are rare, and more importantly, they can be written once and used many times, someone still needs to write them!
Here is some online content on this side of Rust:
- Learn Rust the Dangerous Way - https://cliffle.com/p/dangerust/
- Learn Rust With Entirely Too Many Linked Lists - https://rust-unofficial.github.io/too-many-lists/
- The Rustonomicon - https://doc.rust-lang.org/nomicon/
Wait for an AI company to promote their new model by porting the entire ffmpeg to Rust (half ironically).
Lol, have you ever watch Andrew Kelley speak? I've only seen 3 or 4 talks he's given, but he frequently makes not-so-subtle digs towards Rust. Zig's home page prominently displays "Focus on debugging your application rather than debugging your programming language knowledge" which sounds horrible to me, but is clearly an anti-rust statement. Competition is good, and Rust and Zig cater to different people, but when the primary personality behind Zig is leads the way, it shouldn't be a surprise that some tribalism-influenced followers lean hard into it.
Garbage collection and a higher-level language that controls allocations handles 2/3 of the memory-safety problem space (using memory you shouldn't via use-after-free, or using memory you shouldn't before allocation/via arbitrary address access), but the other 1/3 isn't addressed by GC: out-of-bounds access on properly-allocated structures.
GC-or-not doesn't stop a pointerful language from addressing memory off the end of an array, and the best techniques we have to deal with that today are imperfect (but still pretty good!) compiler inference for BCE, memory protection to limit the scope of possible overreach, or slowing down runtime by inserting checks.
The rest of your points are well-taken; just pointing out that GC isn't the solution to all causes of memory-unsafety, just 2/3 of 'em.
No, it's been known since GC was invented.
> In fact, there was a good two decades after Java released where all the research on memory safety just stopped, because the standard answer became "use a GC".
Having done all of my research on memory safety after Java was released, I find this statement a little exaggerated... (e.g., https://barnowl.org/research/pubs/98-pldi-regions.pdf, https://barnowl.org/research/pubs/07-hotos-linux.pdf)
Yes? Is Fil-C not obviously safer than those?
> I guess you can define a logically consistent taxonomy of languages where Fil-C is the only "safe" language any everything else is unsafe, but then the burden is on you to prove that it's a useful way of thinking about them. Meanwhile, the way that people who consider Go and Java and Rust to be safe and C/C++ to be unsafe will continue to see actual real-world differences in outcomes when using a safe language compared to unsafe ones.
It seems like "can switch on unsafe whenever" vs "has no escape hatches" is an obvious line in the sand and a very useful distinction with real world implications.
> Maybe Fil-C will be able to provide as large benefits to running C safely in production like its proponents claim in the future
Why in the future? It exists and can be used right now. In fact, much of its appeal is being able to use existing code without needing to port to a new language; pragmatism seems like an argument in its favor.
Does cordyceps have a derive macro? I can imagine that helps a lot with correct implemention, though when it comes to linked lists I can see people wanting to do it themselves.
Written by Piotr Sarnacki
on July 28, 2026
When seeing the title of this post, I bet in some people's minds, the first thought was "Rust devs!". This connection is not unfounded. Rust devs tend to be passionate about memory safety. Some of it, I'm sure, may have been caused by a classic language wars attitude: my language is better than yours, and here is why. I'm hoping, though, that most of the Rust devs, who say they care about memory safety, genuinely care about making software safer, and not just criticizing languages that compete with Rust.
The article, surprisingly, is not about Rust devs.
Until recently, most of the memory safety related discourse had a relatively simple basis, at least when considering non-GC, systems programming languages, like C, C++, Zig, and Rust. Rust aims to disallow compiling programs that may introduce memory safety issues (at a cost of sometimes disallowing a program that would have been safe), with an escape hatch in the form of unsafe that allows, among other things, dereferencing raw pointers. C and others leave ensuring memory safety to the programmer. The amount of help from the language differs, for example there is RAII and smart pointers in C++, or defer in Zig, but for the most part nothing stops you from violating memory access.
The situation today is a bit different with a new way to make C, C++, and in the future maybe also Zig, code memory safe: Fil-C. C and C++ code compiled with Fil-C will panic on invalid memory access, like out of bounds access, or use after free. It achieves it by combining GC and InvisiCaps - a way to track memory accessible by a pointer. Zig's author recently announced a new compilation mode for Zig inspired by Fil-C. Fil-C is a very interesting project and I sincerely hope it will succeed and at least some popular C and C++ projects will provide Fil-C compiled releases.
In an ideal world both Rust programmers and C/C++/Zig programmers that care about memory safety would be happy that there are more ways to minimize memory safety vulnerabilities, but alas, we're not living in an ideal world and I can't shake the feeling a lot of the criticism towards Rust recently is disingenuous. If you read Fil-C's author opinions on Twitter, it's blatantly obvious that he dislikes Rust and I've seen him claiming Rust is a memory unsafe language because of ability to bypass some of the Rust guarantees when using unsafe. Andrew Kelley, Zig's author, seems to have a similar stance demonstrated in the fil compilation mode issue title: "introduce an actually memory safe (unlike Rust) compilation mode inspired by Fil-C". Meaning: Rust is unsafe and only Fil-C or Zig's "fil" compilation mode will deal with memory safety related vulnerabilities.
In discussions related to Rust and Fil-C, I've often seen a claim similar to: "if Rust folks really cared about memory safety, they would promote Fil-C and ditch Rust as Fil-C is safer, otherwise they just care about their new shiny language, and not memory safety". That includes Fil-C's author himself. I'm not sure about Andrew Kelley, but the issue title I mentioned earlier feels awfully close. These kinds of arguments are, in my opinion, ignoring reality, and feel like fanaticism and cult-like behaviour that often Rust devs are accused of.
If Fil-C was a drop in replacement with absolutely zero trade-offs, I would maybe partially agree with the sentiment, but it has trade-offs: it's ABI incompatible with non-Fil-C compiled programs, it may be a few times slower in some cases, and it introduces GC. None of these things is a deal breaker for some programs. A lot of programs you use daily could be a few times slower than they are, and you wouldn't even notice. A lot of them also don't link anything dynamically, so the ABI compatibility doesn't matter. But not every software program is a simple utility. There are lots of popular projects, where GC and ABI incompatibility are an issue and there is no way they would ever start using Fil-C like technology, or at least not in a current form. Crucially, the kind of programs that can't use Fil-C are often a good fit for Rust.
But Rust is unsafe, isn't it? It has unsafe after all! If you want to be that strict, or in other words, if you are a memory safety absolutist, that may well be true for you. I, and I hope most people, am more pragmatic than that. There is not a whole lot of data on how secure Rust really is in practice, but to my knowledge there hasn't been a lot of exploitable memory safety vulnerabilities in Rust software, and there are big projects with some data, like 5M+ LOC in Android:
With roughly 5 million lines of Rust in the Android platform and one potential memory safety vulnerability found (and fixed pre-release), our estimated vulnerability density for Rust is 0.2 vuln per 1 million lines (MLOC).
Our historical data for C and C++ shows a density of closer to 1,000 memory safety vulnerabilities per MLOC. Our Rust code is currently tracking at a density orders of magnitude lower: a more than 1000x reduction.
I'm sure these numbers would differ for other projects, but I think by now it is well established that, in practice, Rust minimizes the risk of introducing memory safety issues.
If you could choose a technology that prevents 99.9% of issues in 100% of programs or 100% of issues in 90% of programs, which one would you choose? I have no idea what are the real numbers, but you get the point. Thankfully, we don't have to choose one or the other, contrary to what some people would claim. I would hope that projects written in C/C++/Zig, that can accept the trade-offs, will be available as Fil-C compiled binaries, and software that can't, will be written in languages that either completely or mostly remove the risk of introducing memory safety vulnerabilities.
And I also think it is totally fine to use Rust even if you could use a GC language like Go or Fil-C. Memory safety absolutists would tell you that's not acceptable, although some of them seem to apply memory safety absolutism only when it comes to Rust, and not C, C++, or Zig, go figure. The thing is, programs that can be also written in GC powered languages, often don't need unsafe at all, and programs that need unsafe often couldn't have been using GC. In my experience, people that don't approach solving problem with total fanaticism, tend to consider trade-offs. For many of them, a very small risk of ever running into a severe memory safety issue, is outweighed by other language guarantees (like data races prevention), and other language features. What's more, remember the 1000 memory safety related vulnerabilities per MLOC? With Fil-C they become crashes. It's still better than introducing a security vulnerability issue, but that's quite a lot of crashes to fix. If we're in a realm of fearing relatively uncommon problems, it might be good to state that there were security vulnerabilities in the past that were enabled by an attacker being able to crash a program.
I will end this post saying that if someone cares so much about memory safety that even Rust's 0.2 vulnerabilities per 1M lines of code is not acceptable, I would sure hope they will be criticizing people, who compile YOLO C/C++ and non-fil Zig, as much, if not more, as Rust developers. After all, if you genuinely care about memory safety so strongly that even Rust is not safe enough for you, you wouldn't want to allow people to use even less safe alternatives, would you?
If you like this post please consider following me on Twitter.