Hacker News new | ask | show | jobs
by devit 3074 days ago
Container and iterator code is not safe at all since there is no bounds checking by default and no protection against iterator invalidation, which can both cause writes to memory outside the intended object and thus a catastrophic outcome.

There is no safe subset of C/C++ unless you just don't use pointers or references at all (and refrain from using any library that is not safe which includes large parts of the standard library like all the containers), or you write it in Rust or an equivalent language with lifetimes and linear types and automatically translate it to C/C++ somehow.

2 comments

> unless you just don't use pointers or references at all (and refrain from using any library that is not safe which includes large parts of the standard library like all the containers)

It may seem far fetched, but it might be more practical than you'd think. The SaferCPlusPlus[1] library provides memory-safe implementations of the most commonly used standard library containers, and pointer types that reflect the lifetimes of their target objects. That is to say, there is a practical subset of C++ that is more closely comparable to safe Rust than is conventional C++.

[1] shameless plug: https://github.com/duneroadrunner/SaferCPlusPlus

To be fair, I believe you and the individual you are replying to are treating the word 'safe' differently. Correct; C++ doesn't have a built-in concept of "safe" that is compiler guaranteed and anything written in that, if it isn't written defensively at literally every line of code, falls on the library consumer to handle that.

Rust, CLR/JVM/interpreted languages are 'safe' because the compiler will flat out refuse to do things that are unsafe (with exception to Rust and some non-interpreted languages allowing you to declare portions of code with as 'unsafe'/'hold my beer'). Short of bugs in compiler/standard library, or unsafe code from libraries written in 'unsafe' languages that are consumed by safe languages (which usually requires a bug in the library, not a bug with how the library is called in the "safe" context, but not always), C++ is 'not safe at all' by comparison. I think if you swap the word 'safe', with 'reliable', that was what the individual you were replying to was getting at. 'Safe' in this context is: "The compiler put the foot-shooting-gun in a safe", vs. 'reliable' is "the gun is in my hand, has no safety, and a somewhat light trigger but it's aimed at the target, not my foot ... as far as I know".

You can handle pointers and references safely as well as use components of the standard library that don't do bounds (or a lot of other, "perfectly reasonable but missing for performance/philosophical reasons") checks, but it's up to you.

A really terrible analogy: it's illegal to drive a car where I live with either of the front passengers lacking a safety belt. Heck, you can't even build a car without a number of safety features that regulation requires. It's also got a number of features to help you avoid accidents. If you or someone screws up on the road, you're protected by the safety features and your mastering of driving. That's the 'safe' programming languages that most people use these days. C++/C is like my motorcycle. The only safety features it comes with rely entirely on my skill at not only "not making mistakes" but anticipating the mistakes of others -- I've had several close calls but have been able to maneuver around other distracted drivers/library maintainers, but if I'm not paying attention to everyone/everything around me I'm toast. And even then, some accidents are unavoidable that would have been survivable with a steel cage and a safety-belt[0].

[0] But damn, that bike is fast, and unlike C/C++, it's a lot more fun to use than the safer alternatives.

Reliable is a better word. C++ has lots of features to help you avoid accidents. It's just that you know that certain operations take certain levels of precautions. I like C++. I like the expressiveness it provides. Yes, some things are unsafe, but the amount of time I've spent finding segfaults or other memory errors since becoming proficient is an epsilon in relation to the amount of time I've spent getting all of my crazy template magic to fit into the right spots.