Skip to main content
4 of 4
I think this clarifies the question; please revert if I changed the meaning.
kaya3
  • 20.8k
  • 46
  • 126

Can a language allow raw pointer dereferencing while preserving memory safety?

In Rust, creating a raw pointer is allowed in safe code (i.e. outside of unsafe blocks), but then dereferencing it is unsafe:

let my_num_ptr: *const i32 = &my_num;
let value: i32 = unsafe {*my_num};

Undefined behaviour would only occur in a program which both creates and incorrectly dereferences a raw pointer. So long as one of these operations is only allowed in an unsafe block, memory safety can be guaranteed for programs which have no unsafe blocks.

What if, instead of requiring an unsafe block for the dereference operation, it is instead required for the creation of the raw pointer? For example:

let i: const *u32 = unsafe {&4};
let b = *i;

Or even:

let i: mut *u32 = unsafe {&mut 8};
*i = 5;

In this hypothetical language, operations which create a raw pointer are unsafe (and must only occur in unsafe blocks), but dereferencing them is allowed in safe code, on the basis that it's the programmer's responsibility to make sure when creating the raw pointer that the pointed-to value will stay alive at that memory address for long enough. Is this sound? Would there be any advantages to doing it this way instead of the Rust way?


Note that in Rust, a unsafe block does not mean that the entire program is unsafe, just that there are invariants the compiler can't check, so the programmer is responsible for them. If the programmer has made sure the rules are followed, it's perfectly safe.

In Rust currently, it is undefined behavior to dereference a null pointer, a unaligned pointer, or one that points to uninitialized memory. I'm suggesting that the undefined behavior happens when constructing such a pointer instead.