| ▲ | nzeid 5 days ago |
| > Just using Rust will not magically make your application safe; it will just make it a lot harder to have memory leaks or safety issues. You know, not sure I even agree with the memory leaks part. If you define a memory leak very narrowly as forgetting to free a pointer, this is correct. But in my experience working with many languages including C/C++, forgotten pointers are almost never the problem. You're gonna be dealing with issues involving "peaky" memory usage e.g. erroneously persistent references to objects or bursty memory allocation patterns. And these occur in all languages. |
|
| ▲ | okanat 5 days ago | parent | next [-] |
| Nice thing about Rust is not that you cannot write such code, it is you know exactly where you used peaky memory or re-interpreted something as a unsigned integer or replaced your program stack with something else. All of such cases require unsafe blocks in Rust. It is a screaming indicator "here be dragons". It is the do not press this red button unless you intend to. In C and C++ no such thing exists. It is walking in a minefield. It is worse with C++ because they piled so much stuff, nobody knows on the top of their head how a variable is initialized. The initialization rules are insane: https://accu.org/journals/overload/25/139/brand_2379/ So if you are doing peaky memory stuff with complex partially self-initializing code in C++, there are so many ways of blowing yourself and your entire team up without knowing which bit of code you committed years ago caused it. |
| |
| ▲ | moefh 5 days ago | parent [-] | | > All of such cases require unsafe blocks in Rust. It's true that Rust makes it much harder to leak memory compared to C and even C++, especially when writing idiomatic Rust -- if nothing else, simply because Rust forces the programmer to think more deeply about memory ownership. But it's simply not the case that leaking memory in Rust requires unsafe blocks. There's a section in the Rust book explaining this in detail[1] ("memory leaks are memory safe in Rust"). [1] https://doc.rust-lang.org/book/ch15-06-reference-cycles.html | | |
| ▲ | okanat 5 days ago | parent [-] | | My comment is more of an answer to this > You're gonna be dealing with issues involving "peaky" memory usage e.g. erroneously persistent references to objects I use Rust in a company in a team who made the C++ -> Rust switch for many system services we provide on our embedded devices. I use Rust daily. I am aware that leaking is actually safe. |
|
|
|
| ▲ | AlotOfReading 5 days ago | parent | prev | next [-] |
| C++'s design encourages that kind of allocation "leak" though. The article suggests using smart pointers, so let's take an example from there and mix make_shared with weak_ptr. Congrats, you've now extended the lifetime of the allocation to whatever the lifetime of your weak pointer is. Rc::Weak does the same thing in Rust, but I rarely see anyone use it. |
| |
| ▲ | account42 4 days ago | parent | next [-] | | std::weak_ptr is rarely used in C++ too - "I don't care if this thing goes away but still want to keep a reference to it" is just not good design in most cases. | |
| ▲ | fluoridation 5 days ago | parent | prev [-] | | Huh? What do you mean? The point of std::weak_ptr is that it's non-owning, so it has no effect on the lifetime of the pointed object. | | |
| ▲ | deschutes 5 days ago | parent | next [-] | | You are correct, it does not affect the lifetime of the pointed object (pointee). But a shared_ptr manages at least 3 things: control block lifetime, pointee lifetime, and the lifetime of the underlying storage. The weak pointer shares ownership of the control block but not the pointee. As I understand this is because the weak_ptr needs to modify the control block to try and lock the pointer and to do so it must ensure the control block's lifetime has not ended. (It manages the control blocks lifetime by maintaining a weak count in the control block but that is not really why it shares ownership.) As a bonus trivia, make_shared uses a single allocation for both the control block and the owned object's storage. In this case weak pointers share ownership of the allocation for the pointee in addition to the control block itself. This is viewed as an optimization except in the case where weak pointers may significantly outlive the pointee and you think the "leaked" memory is significant. | |
| ▲ | AlotOfReading 5 days ago | parent | prev [-] | | It has no effect on the lifetime of the object, but it can affect the lifetime of the allocation. The reason is that weak_ptr needs the control block, which make_shared bundles into the same allocation as the object for optimization reasons. Quoting cppreference [0]: If any std::weak_ptr references the control block created by std::make_shared after the lifetime of all shared owners ended, the memory occupied by T persists until all weak owners get destroyed as well, which may be undesirable if sizeof(T) is large.
[0] https://en.cppreference.com/w/cpp/memory/shared_ptr/make_sha... |
|
|
|
| ▲ | loeg 5 days ago | parent | prev | next [-] |
| They're both problems, and forgotten pointers are more common in C, or C++ before 2011 (unique_ptr vs manual new/delete). |
|
| ▲ | andrewmcwatters 5 days ago | parent | prev [-] |
| What's worse in languages like Go, which I love, is that you won't even immediately how to solve this unless you have experience dropping down into doing things you just would have normally done in C or C++. Even the Go authors themselves on Go's website display a process of debugging memory usage that looks identical to a workflow you would have done in C++. So, like, what's the point? Just use C++. I really do think Go is nice, but at this point I would relegate it to the workplace where I know I am working with a highly variable team of developers who in almost all cases will have a very poor background in debugging anything meaningful at all. |