back

by uecker·2y ago·view on hn ↗
The problem is existing practice. GCC has solved this problem for function parameters a long time ago with parameter forward declarations. But other compilers did not copy this GNU extension, and also nothing else really emerged... This makes it hard to convince the committee to adopt it.

In structs there is no existing extension, but a simple accessor macro that casts to a VLA type works already quite well and this can be used by refactoring existing code.

There are still some holes in UBSan, but otherwise I think you can write spatially memory-safe C more or less today without problem. The bigger issue is temporal safety, so the bigger puzzle piece still missing is a pointer ownership model as enforced by the borrow checker in Rust.

1 comments
> There are still some holes in UBSan, but otherwise I think you can write spatially memory-safe C more or less today without problem.

I wouldn't call it a solved problem until gcc and clang have an auto-inserts-bound-check flag that does the equivalent of a Rust panic on every array access if it's out-of-bounds, is considered usable on production code [1], and works on most major projects (that care enough to change their source to take advantage of this flag). Overall, the problem isn't so much that we don't know how to write safe C code, it's that the compiler doesn't quite have enough information to catch silly programmer mistakes, and there current situation is juuuuust bad enough that we can't feasibly make code that doesn't tell the compiler enough error out during compilation.

> The bigger issue is temporal safety, so the bigger puzzle piece still missing is a pointer ownership model as enforced by the borrow checker in Rust.

Temporal safety is interesting in part because it's not clear to me that there currently exists a good solution here. The main problem, like existing partial solutions for spatial memory safety, is that the patterns to make it work well are known, but programmers tend to struggle to apply all of the rules correctly. Rust's borrow checker is definitely a step up from C/C++, but at the same time, there are several ownership models that it struggles to be able to express correctly, even if you ignore the many-readers-xor-one-writer rule that it also imposes. Classic examples are linked lists or self-referential structs, but even something like Windows' IOCP can trip up Rust's lifetime system.

Although, at the very least, a way to distinguish between "I'm only going to use this pointer until the end of the function call" and "I'm going to be responsible for freeing this pointer you give me, please don't use it any more" would be welcome to have, even if it is a very partial solution.

[1] Don't get me wrong: the development of the sanitizers is an important and useful tool for C/C++, and I strongly encourage their use in test environments to catch issues. It's just that they don't meet the bar to consider the issue solved.

Sanitizers without runtime, i.e. -fsanitize=bounds -fsanitize-trap=bounds, can be used in production? And I think it can be used on existing projects by refactoring. Catching this at compile-time would be better, but Rust also can't do it and it is not needed for memory safety. And I think the solution C converges to (dependent types) actually would allow this is many cases in the future, while this is difficult without them. I fully agree about your other points.