You know sanitizers and static analysis tools exist, and have existed for decades, and have been the basis for the work done in Rust and other "safe" languages?
Also, a disciplined C programmer will always keep the size of the buffer near the buffer itself.
For example, using something like this is perfectly safe (though, we can see the performance hit of those if-statements if used intensively):
This comes up from time-to-time. Surely, there's some caveat here either for performance or other reasons (I'm not a solid C programmer enough to know the if this hypothesis is viable or not). If it was so simple this approach would be ubiquitous and C would be safe. What am I missing?
> If it was so simple this approach would be ubiquitous and C would be safe.
There are some unavoidable footguns (notably around unintended integer promotions and overflow), but for four decades life-critical machinery like rockets, munitions, airplanes, heavy industrial equipment, automotive control systems ... and more have been controlled by C code, and the number of lives lost due to bugs you are complaining about are statistical noise.
It's been used extensively in products that could never be patched or updated after release, and could only be recalled, and yet I recall only a few instances when bugs lead to lives lost, and in at least one of those cases the culprit was identified to be something other than the language (i.e. those same errors or worse would have resulted even if a different language was used due to the dev process and architecture).
These bugs are not even a rounding error! So it would seem that writing safe C is ubiquitous. You're seeing the statistical noise and concluding it is representative of all software written in C, when you should be looking at all that noise and saying "is this all there is?"
A chainsaw is not safe. But you can learn to use it safely.
Replace chainsaw with:
- knife
- guns
- C programming language
There are tools and methods (and a lot of discipline) to ensure safety in C:
- compiler's sanitizers[0]:
- address: to detect out-of-bounds and use-after-free bugs
- pointer-compare, pointer-subtract: to detect invalid operation when pointers are non null
- shadow-call-stack: to detect return address overwrites (stack buffer overflows)
- thread: to detect data races
- leak: to detect memory leaks
- undefined: to detect undefined behaviors
- ...
- static analysis tools, like Splint[1]
Would you ride a motorbike without the proper protections (helmet, heavy jacket, ...) ?
Also, a disciplined C programmer will always keep the size of the buffer near the buffer itself.
For example, using something like this is perfectly safe (though, we can see the performance hit of those if-statements if used intensively):
It is possible to write safe C code, but it takes understanding of the language, sometimes of the compiler as well.The whole "There is no programmer who don't make mistakes" argument is fallacious at best.
C is like a chainsaw, there are certain rules on how to use it safely. Yes you can cut limbs with a chainsaw, that does not make the chainsaw useless.