6 ms·
I write C and C++ for a living, and the reason I prefer Rust to them is definitely not memory safety, that's just a nice plus. I think that lots of C/C++ devel
by qalmakka 6y ago
I write C and C++ for a living, and the reason I prefer Rust to them is definitely not memory safety, that's just a nice plus.
I think that lots of C/C++ developers have never thought for long about how you end up having to care about the same things in C and C++ too.
In C++, you have to think about exception safety, lifetimes and move semantics when you write your code; you have to know if a variable is moveable, if it is worth it to do so, when and by whom it will be destroyed, etc. If you start writing modern and sane C++, you just realise that lots of the patterns you find yourself using are all things Rust already does automatically enforces for you at the language level.
Meanwhile, often people forget that while C just does not care about what you do with memory, you still _must_ remember that objects still have lifetimes, memory still has ownership; the main difference is that the compiler neither enforces nor checks what you're doing with it. Just like in Rust and C++ you must know if a certain resource is yours or not, and you need to be actively aware of it and manage it properly by clearly documenting how it should be managed and where you expect it to change ownership.
I cannot count how many times I saw C libraries forcing you to use reference-counted objects on the heap just to get out of the messy they used pointers. That is, lots of people find that some of their code references random objects in unsound places without any regard about ownership, and then they get need to find a way around it; refcounting is often the easiest solution. And don't get me started about people managing objects like this:
struct obj;
struct obj* obj_new();
void obj_delete(struct obj*);
that is, simply forcing you to use heap allocation using malloc() (rarely, the objects might come from a pool, but it's not that frequent) without considering that you're forcing people to allocate memory (and fragmenting the heap) for short-lived objects that could have well resided on the stack; it also makes a library unusable for those people who might want to use your library on a system that has no heap or has an heterogeneous memory model where not all memory is the same.
I have seen a handful C libraries actually care about allocators, but they are definitely not the norm. This is also the reason why I started using C++ on embedded systems such as the ESP32, where flash is relatively abundant (it gets up to 16 MB in some configurations) but internal, on chip ram is still scarce for lots of advanced use cases (~512K) and you need to rely on SPI-connected RAM to actually get work done. C++ libraries that use allocators can be used on such systems without any issue, by simply writing your own allocator; Rust still has not such a nice allocator system in place, but at least it allows you to use the stack and return almost everything by value.
In the end, my point of view is that switching from C or C++ to Rust should not feel like you're radically changing the way you code regarding ownership and memory management, because it's orthogonal to the language; it's something you that always needs to be a crucial point in the code you design. In my experience I learnt that 99% of the time when you feel that Rust is hindering your design it's because your design is either unsound or depends on trusting safety assumptions that are enforced outside of your program (i.e. the OS is guaranteeing this, or this is not physically possible).
Rust will always guarantee safety as long as the postulates it lies on hold, but you should not expect it to make a potentially unsafe C library 100% sound because the language can only go as far ahead as ensuring the code you wrote in it is doing exactly what you've said it should do, and nothing more.
Lots of C libraries are often based on an assumption of trust. They just assume that some things will always happen in a certain way, or that certain events are not likely o serious enough to justify wasting time on writing code to check them. This is, I think, the reason some things can't be directly model on top of Rust, because Rust has been made explicitly to force you to eliminate the occurrence of certain errors, so you either have to implement yourself boilerplate code to guarantee your library behaves like Rust wants it to behave, or you accept the need of writing unsafe code.
- pjmlp 6y ago> switching from C or C++ to Rust should not feel like you're radically changing the way you code regarding ownership and memory management, Until you try to do GUIs, or imagine how something like a GUI designer would work, and then the fun starts. Unless there is some improvements in this area, I don't see Rust replacing the symbiotic relationship that C and C++ enjoy with native GUI toolkits, either on their own or coupled with managed languages.
- qalmakka 6y agoBecause, IMHO, a lot if not every of the GUI frameworks have been born by necessity and has a lot of cruft around that requires type magic incompatible with a strict language like Rust. GUI toolkits are often really old (more than 20 years old at least) and have been either hastily hacked in C (often in C89, like Win32 and GTK+, which is famous to abuse refcounting and C macros and is a prime example of what I was mentioning above as a poorly designed library), or have been designed in C++ before C++11, so they largely depend on nasty hacks and practises that are considered obsolete in modern C++ (like Qt). Other GUI toolkits are designed around modern garbage collected languages (see WinForms, WPF, Swing, ...) so they're not really usable from non-managed languages. Cocoa is in a weird spot, being written in a pretty-much duck-typed language like Objective-C. My point is that IMHO it's not Rust itself that's not suited for GUIs, but it's the GUI toolkits that have often aged very badly and are out of touch with modern software development. The ugliness of developing UIs with the old frameworks is I think one of the main reasons why the web has taken over, and why others such as Qt have largely moved to a declarative approach with things like QtQuick (i.e. "almost JS") or Apple's SwiftUI. It's all about keeping development sane, something Microsoft has IMHO canned several times by trying fix the mess they made with Win32, only by making it worse creating a dozen of competing, almost incompatible toolkits. The fact that the newest of them, written since its inception in modern C++ (C++/WinRT) has a nice to use Rust alternative (Rust/WinRT) shows that the problem wasn't the language all along.
- pjmlp 6y agoGiven how C++/WinRT currently represents a huge step back from C++/CX tooling capabilities, and Rust/WinRT is still doing baby steps to match C++/WinRT, I rather wait and see. I bet just like it happened with C++/CX and C++/WinRT, Microsoft will be the major user, while everyone else outside Redmond will use .NET instead. Ralf Levien has already posted several blog post how even writing a Rust specific UI toolkit from scratch is not as straightforward as he thought it would be. https://raphlinus.github.io/rust/druid/2020/09/28/rust-2021.html https://raphlinus.github.io/rust/druid/2020/09/28/rust-2021.... The Web has taken over because many junior devs don't know any better, and I am really happy that WebAssembly + WebGL is already bringing Flash like tooling back to the Web. https://platform.uno/ https://platform.uno/