4 ms·
Box::leak was added two years later in November 2017 https://github.com/rust-lang/rust/commit/360ce780fdae0dcb31cfa0f7ffa8a6c9fd62ed32 https://github.com/rust-l
by milesrout 2y ago
Box::leak was added two years later in November 2017 https://github.com/rust-lang/rust/commit/360ce780fdae0dcb31cfa0f7ffa8a6c9fd62ed32 https://github.com/rust-lang/rust/commit/360ce780fdae0dcb31c...
>Crashes, stability, and performance issues are still not safety issues since there’s so many ways to cause those beyond memory leaks.
They aren't safety issues according to Rust's definition, but Rust's definition of "unsafe" is basically just "whatever Rust prevents". But that is just begging the question: they don't stop being serious safety issues just because Rust can't prevent them.
If Rust said it dealt with most safety issues, or the most serious safety issues, or similar, that would be fine. Instead the situation is that they define data races as unsafe (because Rust prevents data races) but race conditions as safe (because Rust does not prevent them in general) even though obviously race conditions are a serious safety issue.
For example you cannot get memory leaks in a language without mutation, and therefore without cyclic data structures. And in fact Rust has no cyclic data structures naturally, as far as I am aware: all cyclic data structures require some "unsafe" somewhere, even if it is inside RefCell/Rc in most cases. So truly safe Rust (Rust without any unsafe at all) is leakfree, I think?
- Rusky 2y ago> Rust's definition of "unsafe" is basically just "whatever Rust prevents". It's not that circular. Rust defines data races as unsafe because they can lead to reads that produce corrupt values, outside the set of possibilities defined by their type. It defines memory leaks as safe because they cannot lead to this situation. That is the yardstick for what makes something safe or unsafe. It is the same yardstick used by other memory-safe languages- for instance, despite your claims to the contrary, garbage collectors do not and cannot guarantee a total lack of garbage. They have a lot of slack to let the garbage build up and then collect it all at once, or in some situations never collect it at all. There are plenty of undesirable behaviors that fall outside of this definition of unsafety. Memory leaks are simply one example.
- milesrout 2y ago>It defines memory leaks as safe because they cannot lead to this situation. They can't now. They could up to and almost including 1.0. At that point the consensus was that memory leaks were unsafe and so unsafe code could rely on them not happening. That code was not incorrect! It just had assumptions that were false. One solution was to make those assumptions true by outlawing memory leaks. The original memory leak hack to trigger memory corruption was fairly fiendish in combination with scoped threads (IIRC). >There are plenty of undesirable behaviors that fall outside of this definition of unsafety. Memory leaks are simply one example. That is my whole point. It is a useless definition cherry-picked by Rust because it is what Rust, in theory, prevents. It does not precede Rust. Rust precedes it. >It is the same yardstick used by other memory-safe languages- for instance, despite your claims to the contrary, garbage collectors do not and cannot guarantee a total lack of garbage. They have a lot of slack to let the garbage build up and then collect it all at once, or in some situations never collect it at all. If it will eventually be collected then it isn't a memory leak. Most actual safe languages don't let you write integer overflow.
- Rusky 2y ago> They can't now. They could up to and almost including 1.0. At that point the consensus was that memory leaks were unsafe and so unsafe code could rely on them not happening. That code was not incorrect! This is not how it worked, no. It was never memory leaks per se that led to unsoundness there. It was skipping destructors. You could have the exact same unsoundness if you freed the object without running the rest of its destructor first. That part was the design choice Rust made- make destructors optional and change the scoped threads API, or make destructors required and keep the scoped threads API. There is an underlying definition of memory safety (or more generally "soundness") that precedes Rust. It is of course defined in terms of a language's "abstract machine," but that doesn't mean Rust has complete freedom to declare any behavior as safe. Memory safety is a particular type of consistency within that abstract machine. This is why the exact set of undesirable-but-safe operations varies between memory-safe languages. Data races are unsafe in Rust, but they are safe in Java, because Java's abstract machine is defined in such a way that data races cannot lead to values that don't match their types.
- vlovich123 2y agoSure, safety is a relative moving target. There’s no way to prevent race conditions unless you have proofs. And then there’s no way to enforce that your proof is written correctly. It’s turtles all the way down. Rust is a Paretto frontier of safety for AOT high performance languages. Even for race conditions I suspect the tools Rust has for managing concurrency-related issues make it less prone to such issues than other languages. The problem is you’re creating a hypothetical gold standard that doesn’t exist (indeed I believe it can’t exist) and then judging Rust on that faux standard and complaining that Rust chooses a different standard. That’s the thing though - every language can define whatever metrics they want and languages like C/C++ struggle to define any metrics that they win vs Rust. > For example you cannot get memory leaks in a language without mutation, and therefore without cyclic data structures This does not follow. Without any mutation of any kind, you can’t even allocate memory in the first place (how do you think a memory allocator works?). And you can totally get memory leaks without mutation however you narrowly define it because nothing prevents you from having a long-lived reference that you don’t release as soon as possible. That’s why memory leaks are still a thing in Java because there’s technically a live reference to the memory. No cycles or mutations needed. > So truly safe Rust (Rust without any unsafe at all) is leakfree, I think? Again, Box::leak is 100% safe and requires no unsafe at all. Same with std::mem::forget. But even if you exclude APIs like that that intentionally just forget about the value, again nothing stops you from retaining a reference forever in some global to keep it alive.
- milesrout 2y agoWhat is a type system except a bunch of proofs? You can encode some program correctness properties into types. Elevating the ones you happen to be able to encode and calling them "safety" and the rest "correctness" is just marketing. I am not creating a gold standard because as far as I am concerned, it is all just correctness. There aren't morally more and less important correctness properties for general programs: different properties matter more or less for different programs. >Without any mutation of any kind, you can’t even allocate memory in the first place (how do you think a memory allocator works?). data L t = E | C t (L t) data N = Z | S N nums Z = E nums (S n) = C (S n) (nums n) You cannot express a reference cycle in a pure functional language but they still have allocation. However I don't know why I brought this up, because you can also eliminate all memory leaks by just using garbage collection - you don't need to have immutable and acyclic data structures. >Again, Box::leak is 100% safe and requires no unsafe at all. Same with std::mem::forget. #[inline] pub fn leak(b: Box<T>) -> &'static mut T { unsafe { &mut *Box::into_raw(b) } } They are implemented using unsafe. There is no way to implement Box without unsafe. If you retain a reference in a global then it is NOT a memory leak! The variable is still accessible from the program. You can't just forget about the value: its name is right there, accessible. That is not a memory leak, except by complete abuse of terminology. The concept of "inaccessible and uncollectable memory, which cannot be used or reclaimed" is a useful one. Your definition of a memory leak seems to be... any memory usage at all?