3 ms·
In Rust, dereferencing a pointer is unsafe and so must be isolated within an `unsafe` block — but creating a dangling pointer is not unsafe. What this means is
by rectang 6y ago
In Rust, dereferencing a pointer is unsafe and so must be isolated within an `unsafe` block — but creating a dangling pointer is not unsafe.
What this means is that as soon as you add `unsafe` code which accepts a pointer argument, all the supposedly "safe" code which can affect this pointer argument becomes a potential source of memory errors.
To me, this was unintuitive — I expected the `unsafe` block to require an extra level of scrutiny, not the surrounding code. After making an error similar to the one described in this post, I wondered, "why isn't creating a dangling pointer unsafe?" But after following that train of thought I realized that vast amounts of code would be pulled into `unsafe` blocks as a consequence, so it's not a viable approach — and thus it became apparent why only dereferencing is unsafe.
The lesson seems to be that dereferencing requires extreme care, but I wish potential errors weren't so subtle. The `as_ptr` family of functions has been tripping people up for a long time:
https://users.rust-lang.org/t/cstring-as-ptr-is-incredibly-unsafe/11431 https://users.rust-lang.org/t/cstring-as-ptr-is-incredibly-u...
- stefan_ 6y agoIn general unsafe should be viral: you can't call unsafe without yourself being unsafe. But it hits the same "snag", then nothing works anymore.
- nynx 6y agoThis is not true. Rust is based around the idea of encapsulating unsafety within interfaces that are safe to use.
- Jweb_Guru 6y agoIf `unsafe` were viral it would be useless. Syntactically ill-typed code can still be proven semantically well-typed, and `unsafe` is intended as a marker that the proof of semantic soundness lies outside of Rust's type system. If there is no proof (at least an informal one), you shouldn't be using unsafe, generally speaking.
- jdc 6y agoI wonder what a good approach to safe pointer arithmetic would be.
- pornel 6y agoRust's actually-safe pointer arithmetic is done via slices (because it's necessary to track the length): slice = &slice[1..]; It compiles to roughly `ptr++; len--;` and a bounds check if necessary. `1234 as *const u8` and `ptr.offset(n)` are also safe, because Rust allows invalid/dangling pointers to exist if they're never dereferenced.
- rectang 6y agoThis answer addresses the letter of jdc's musing, but not the gist. The code that you've supplied may be "safe", but the issue is that there's no way to constrain pointer arithmetic such that the result always points at a valid location which can withstand dereferencing.