Hacker News new | ask | show | jobs
by felipefar 613 days ago
They solve the use-after-free issue by keeping pointed objects alive, not by helping you think better about object lifetimes in your code. That means some objects will live for longer than you initially thought they would, and potentially even introduce circular references. Added to that, they also introduce random, unpredictable slowdowns in your application to run their algorithms.

I'm not yet sold on Rust, but exploring alternatives for achieving memory safety without needing to put on a GC is commendable.

1 comments

> They solve the use-after-free issue by keeping pointed objects alive

That's not at all what Fil-C's garbage collector does.

If you free() an object in Fil-C, then the capability is marked free and the next GC cycle will:

- Delete the object.

- Repoint all capabilities that referred to that object to point to the free singleton capability instead.

This ensures that:

- Freeing an object really does free it, regardless of whether the GC sees it as reachable.

- Using an object after freeing it is guaranteed to trap with a Fil-C panic, and that panic is guaranteed to report that the object has been freed so you know why you're trapping.

Also, as a bonus, if you don't ever free your objects, then the Fil-C GC will delete them for you once they become unreachable. So, you can write Java-style code in C++, if you want.

> That means some objects will live for longer than you initially thought they would, and potentially even introduce circular references.

No idea what you mean there. Maybe you're thinking of reference counting, which isn't a form of garbage collection. (Reference counting is different precisely because it cannot handle cycles.)

> unpredictable slowdowns in your application to run their algorithms.

Fil-C's garbage collector is 100% concurrent. It'll never pause your shit.

Fil-C sounds very similar to Google's MiraclePtr.

However, Safe C++ (Circle) and Rust do much more than that. They are not limited to pointers on the heap, and the borrowing rules work for all references including the stack. They also work for references that need to be logically short even when the data is not freed, e.g. internal references to data protected by a mutex don't outlive unlocking of the mutex. And all of that is at zero runtime cost, and by guaranteeing the code correctly doesn't create dangling references in the first place, not merely by softening the blow of run-time failures of buggy code.

Fil-C is nothing like MiraclePtr. Fil-C gives you comprehensive memory safety.

Yes, it handles references to the stack. Misuse traps or leads to other safe outcomes.

Fil-C makes it so races have memory safe outcomes (like Java).

Circle and Rust are strictly less safe than Fil-C, since both have unsafe escape hatches. Fil-C doesn't even have an unsafe escape hatch.

Oh, I remember this project now. I see it still advertises 3x-10x overhead. To me this takes it out of being a contender in the systems programming space.

This can't be dismissed as a mere quality-of-implementation detail. C and C++ are used because they don't have such overheads, so it takes away the primary reason to use these languages. When non-negligible overhead is not a problem, there are plenty of nicer languages to choose from for writing new code.

This leaves Fil-C in a role of a sandbox for legacy code, when there's some unsafe C code that won't be rewritten, but still needs to be contained at any cost. But here you need to compete with WASM and RLBox which have lower-overhead implementations.

Fil-C was 200x slower when I started and the latest overheads are lower than 2x in a lot of cases. It’s getting faster every month, though I don’t always update the docs to say the latest numbers (because I’m too busy actually making it faster).

I think the reason why folks end up using C is often because they have a gigantic amount of C code and for those folks, Fil-C could easily be good enough as is.

But dismissing it as a contender because the perf isn’t there today even as it’s getting steadily faster (on a super aggressive trajectory) is a bit unfair, I think.

The success of this project is going to be very non-linear with speed, so it really hangs on where your speed improvements will plateau.

If you get below 2x, you can compete with WASM and ASAN. If you get it down to 1.1x-1.2x, you can compete with RLBox. If you get down to 1.05 you can call it software-emulated CHERI and kill the whole hardware line before it even comes out.

If you get it down to 1.01x, Rust will copy you, and then beat you by skipping checks on borrowed references ;)