6 ms·
> I just do not see why people seem to use "unsafe" so much Because it’s impossible to implement any non-trivial data structures in safe Rust. Even Vec has uns
by Const-me 2y ago
> I just do not see why people seem to use "unsafe" so much
Because it’s impossible to implement any non-trivial data structures in safe Rust. Even Vec has unsafe code in the implementation to allocate heap memory. When you need efficient trees or graphs (I doubt any non-trivial software doesn’t need at least one of them), unsafe code is the only reasonable choice.
C++ does pretty much the same under the hood, but that’s OK because the entire language is unsafe.
C# has an unsafe subset of the language with more features, just like Rust. However, it runs inside a memory-safe garbage collected runtime. Even List and Dictionary data structures from the standard library are implemented with safe subset of the language. Efficient trees and graphs are also trivial to implement in safe C#, thanks to the GC.
- deleted 2y ago[deleted]
- bubaumba 2y ago>> I just do not see why people seem to use "unsafe" so much >Because it’s impossible to implement any non-trivial data structures in safe Rust. Even Vec has unsafe code Hmm.. wasn't memory safety the main selling point for rust? If not the only. Now mix of two languages looks even worst than one complex. Especially taking into account that it can be paired with safe language from long list. Don't know what rust fans are thinking, but from outside it doesn't look very attractive. Definitely not enough to make a switch. Julia looked better at first, but turned out to be just a graveyard of abandoned academic projects.
- eddd-ddde 2y agoYou fan wrap unsafe implementations with safe APIs. The point is there's an explicit boundary between unsafe an safe.
- pcwalton 2y ago> Now mix of two languages looks even worst than one complex. The point is that the vast majority of code doesn't have to be unsafe. Empirically, Rust code has far fewer memory safety problems than non-memory-safe languages.
- deleted 2y ago[deleted]
- TheRoque 2y agoMemory safety without gc is not the only reason people use rust. It's also nicer to use than C++ for multiple reasons (language features, included package manager, easy to integrate tests...)
- guappa 2y agoI use Qt, and I think if you have the Qt libraries then C++ is way better than rust. Most things are there instead of having to go and find a crate and then decide which one to use and hope it will remain maintained.
- okanat 2y agoNope it isn't. You just aren't experienced in system programming. Working with hardware is unsafe since it has state that one cannot completely encapsulate in a single program. The entire specific design of a chip isn't available to programmer; only the machine code is. We usually don't know how a processor decides to cache things or switch to kernel permission level. Usually this isn't even the level we're at, OSes have private internals that change behind the programs and they are not accessible from user space. Pressing Ctrl+C to interrupt changes so many things in memory, it would be outright impossible to write programs that handle every single thing. The fundamental / syntactic promise of Rust is providing mechanisms to handle and encapsulate unsafety such that it is possible to construct a set of libraries that handle the unsafety in designated places. Therefore the rest of the program can be mathematically proven to be safe. Only the unsafe parts can be unsafe. Coming from Java or Go or Js or Python angle wouldn't be the same. Those languages don't come with mechanisms to let you to make system calls directly or handle the precise memory structure of the data which is necessary when one is communicating with hardware or the OS or just wants to have an acceptable amount of performance. In C++, the compiler can literally remove your code if you sum or multiply integers wrong or assume the char is signed/unsigned. There is no designated syntax that limits the places possible memory overflow error happen. The design of the language is such that some most trivial oversight can break your program silently and significantly. It is too broad so it is not possible to create a safe and mathematically proven and performant subset with the C and C++ syntax. It is possible with Rust. It is like the difference of chips that didn't have a hardware mechanism to switch between user and kernel mode so everything was simply "all programs should behave well and no writes to other programs' memory pinky promise". Rust doesn't leave this just as a possibility. Its standard library is mostly safe and one can already write completely safe and useful utilities with the standard library. The purpose of the standard library is provide you ways to avoid unsafe as much as possible. Of course more hardware access or extremely efficient implementations would require unsafe. However again, only the unsafe parts can cause safety bugs. They are much easier to find and debug compared to C++. People write libraries for encapsulating unsafe so there are even less places that use unsafe. If people are out of their C++ habit, reaching for the big unsafe stick way too often, then they are using Rust wrong. Whatever you do, there will be always a need for people and software that enables a certain hardware mode, multiply matrices fast, allocates a part of display for rendering a window etc. We can encapsulate the critical parts of those operations with unsafe and the rest of the business logic can be safe.
- School-Cotton 2y ago> Hmm.. wasn't memory safety the main selling point for rust? The vast majority of Rust programmers aren't spending their time re-implementing core data structures like Vec, so memory safety (and the fact that library authors can build safe abstractions on top of unsafe code, which is impossible in C or C++) still benefits them.
- jltsiren 2y agoNon-trivial data structures are often just a bunch of arrays/maps with additional semantics. You may consider implementing/using unchecked versions of basic operations for a little bit of additional performance. If you implement (de)serialization yourself, you may need unsafe code. Sometimes the safety of deserialization may be a convenient lie, if checking the invariants fully would be too expensive. And sometimes you may want to expose internal helper functions for various purposes, which may have to be marked unsafe if they can break the invariants. Beyond that, you only need unsafe code for specific kinds of data structures. At least in my experience.
- Const-me 2y ago> Non-trivial data structures are often just a bunch of arrays/maps with additional semantics This might be fine for code which consumes data structures implemented by other people. The approach is not good when you actually need to implement data structures in your program. In modern world this is especially bad for a low-level language (marketed as high performance, BTW) because the gap between memory latency and compute performance is now huge. You do need efficient data structures, which often implies developing custom ones for specific use cases. This is required to saturate CPU cores as opposed to stalling on RAM latency while chasing pointers, or on cache coherency protocol while incrementing/decrementing reference counters from multiple CPU cores. Interestingly, neither C++ nor C# has that boundary, for different reasons: C++ is completely unsafe, and safe C# supports almost all data structures (except really weird ones like XOR linked lists) because GC.
- jltsiren 2y agoI used to think like that. Then C++11 arrived, and I realized I could get effectively the same performance with containers and move semantics, while spending less effort on writing and debugging the code. If you need an array for your custom data structure, a standard library vector is almost always good enough. Associative arrays are a bit more tricky, but you should be able to find a handful of map implementations that cover most of your needs. And when you need a custom one, you can often implement it on top of the standard library vector.
- pcwalton 2y ago> When you need efficient trees or graphs (I doubt any non-trivial software doesn’t need at least one of them), unsafe code is the only reasonable choice. To name one example, the AnimationGraph in Bevy is implemented with petgraph, which is built using adjacency lists, and doesn't use any unsafe code in any of the parts that we use. It is very high-performance, as animation evaluation has to be.
- Const-me 2y ago> It is very high-performance, as animation evaluation has to be Are you sure evaluating these animations is performance critical? I doubt games have enough data to saturate a CPU core doing that. Screens only have 2-8 megapixels; animated objects need to be much larger than 1 pixel. If you animate bones for skeletal animation that’s still not much data to compute because real life people have less than 256 bones. You don’t need much more than that even if your models have fancy manually-animated clothes.
- refulgentis 2y ago> Are you sure evaluating these animations is performance critical? Isn't this obviously true? A key part of UI work is avoiding "jank", which commonly refers to skipped frames. > I doubt games have enough data to saturate a CPU core doing that. Got a bit lost here: games? > Screens only have 2-8 megapixels. 4 bytes per pixel, 32 MB/frame. 120 frames / sec = 8 ms/frame. 3.84 GB/second. > animated objects need to be much larger than 1 pixel. Got lost again here. In general, I'm lost. First, there's a weak claim that all performant data structures in Rust must use unsafe code. I don't think the author meant all performant data structures must use unsafe code. I assume they meant "a Rust data structure with unsafe code will outperform an equivalent Rust data structure with only safe code" Then, someone mentions a 3D renderer, written in Rust, is using a data structure with only safe code. I don't understand how questioning if its truly performant, then arguing rendering 3D isn't that hard, is relevant.
- Const-me 2y ago> Isn't this obviously true? To an extent sure, but we’re talking about low level micro-optimizations. Games don’t animate individual pixels. I don’t think animating 1000 things per frame gonna saturate a CPU core doing these computations, which means the code doing that is not actually performance critical. > Got a bit lost here: games? I searched the internets for “Bevy Engine” and found this web site https://bevyengine.org/ https://bevyengine.org/ which says “game engine”. I wonder is there another Bevy unrelated to games? > 3.84 GB/second In modern games none of that bandwidth is processed on CPU. Games use GPU for that, which don’t run Rust. > there's a weak claim that all performant data structures in Rust must use unsafe code Weak claim? Look at the source code of data structures implemented by Rust standard library. You will find unsafe code everywhere. When you need custom data structures instead of merely using the standard ones you will have to do the same, because safe Rust is fundamentally limited in that regard.
- dartos 2y ago> Because it’s impossible to implement any non-trivial data structures in safe Rust This is why I think rust is great for application programmers. Honestly high performance web servers, games, anything in that realm it's pretty good for. Low level systems and high performance data structures are better implemented with direct memory management, but the consumers of those libraries shouldn't have that same burden (as much as possible). Granted, I haven't worked with rust enough to run into issues with other people's unsafe code.