3 ms·
You're mistaken if you think that anything in C++11/14 makes it memory-safe like Rust guarantees. C++11/14 lets you assign a std::unique_ptr to another variabl
by gilgoomesh 12y ago
You're mistaken if you think that anything in C++11/14 makes it memory-safe like Rust guarantees.
C++11/14 lets you assign a std::unique_ptr to another variable then re-use the original variable, causing a null dereference. You can also have a reference to the same std::unique_ptr from two different threads causing a race-condition on the underlying pointer.
There is no bounds checking on std::vector by default. You can bounds check a std::vector (using "at" or various configuration/compiler settings which change the semantics of the standard library) but by default, it is not checked.
Fundamentally, the issue is that C++ lets you have null pointers and references (yes, references can be null). It lets you use before initializing. It lets you run out of bounds. It lets you access the same variable from multiple threads without any safety. Yes, idiomatically, none of these should be an issue but it's not possible to be a perfect programmer.
Rust forces idiomatic memory management and eliminates all these issues. If you make a memory safety mistake, the compiler will force you to fix it.
- jguegant 12y agoYour points are clearly valids. But wouldn't some of them corrected by a strict mode? - For instance, the reuse of the original variable could be deduced by the compiler. - The bound checking for std::vector can effectively be enable. One could imagine an std::strict_vector that do so. What I am wondering is: does the same idiomatic memory management applied to C++ would require some huge tweaks to the language, some bad tricks, new keywords, or can it be done without changing its design but enforcing some rules? I, for instance, have no clues how to deal with your "one unique_ptr two threads" problem. Could it be done in an elegant way in C++?
- lomnakkus 12y agoLinear types (as in Rust) can prevent (at compile time) some of the more trivial use-after-free issues e.g. for unique_ptr, but I think the main reasons you won't see undefined behavior eliminated from C++ wholesale is that it a) often requires extensive support at runtime (see ASAN, UBSAN, etc.) and b) presents a huge barrier to optimization in certain cases and c) (thus) is going to be waaay too slow for production use. (I.e. if C++ were to go in this direction someone would basically either "fork" C++ or a new (similar) language would supplant it.) Unfortunately, currently no "sufficiently smart compiler" exists, so that high-level code can be optimized sufficiently to beat what a good micro-optimizing C++ compiler (which can assume that no undefined behavior can occur at runtime) can achieve.
- kibwen 12y agoUndefined behavior does permit optimizations, yes, but I think you're overselling its benefit. Rust doesn't have undefined behavior and there are many instances where its strict semantics mean that it is far more optimizable and runtime-efficient than C++ (though some of those optimizations are yet to be implemented).
- lomnakkus 12y agoPerhaps, these days you're right -- assuming you want to only support mainstream architectures. These days you can mostly rely on all mainstream architectures to do something sensible with e.g. signed integer overflow[1] or excessive shifting, but that wasn't necessarily the case when most of C++ was standardized. As an example of a similar nature -- as I'm sure you know -- Rust has chosen to not abort/panic on signed overflow although almost all instances of such are most probably plain logic errors and could lead to security problems[2]. As far as I could understand, this was for performance reasons. Granted, this is not quite as disastrous for general program correctness as UB, but it can lead to security bugs. Point being: Underspecification can give you a lot of leeway in how you do something -- and that can be hugely valuable in practice. Just as an aside: Personally I tend to prefer safety over performance, but I was persuaded that UB is valuable by comments that Chandler Carruth of Clang (and now ISO C++ committee) fame made about UB actually being essential to optimization in C++. Sorry, can't remember where, exactly, those comments were made. [1] Everybody's probably using two's-complement (for good reasons). [2] Not nearly as easily as plain buffer overflows, but there have been a fair few of these that have been exploitable.
- FreeFull 12y agoRust will actually now panic when not in release mode when an integer overflow happens, as opposed to how things used to be before, where it would just accept the overflow silently with wrapping semantics. Here is the discussion from when this change was announced: http://internals.rust-lang.org/t/a-tale-of-twos-complement/1062 http://internals.rust-lang.org/t/a-tale-of-twos-complement/1...
- the_why_of_y 12y agoA "safe mode" in C++ is completely impossible in practice, because C++ does not have a module system but an automated text copy-and-paste mechanism (the preprocessor). Hence your "strict" mode would refuse to compile any unsafe constructs in your standard C++ library headers, boost headers, Qt headers, libc headers, or any other headers of popular and mature libraries that made you choose the C++ language in the first place. If you can't re-use any code anyway, why not pick a sane language?