fn main() {
let val = 0;
unsafe { foo(&val) }
}
extern "C" {
pub fn foo(val: *const u32);
}
Implementation in C:
void foo(unsigned* val) { *val=1; }
Of course, I should pass val: *mut u32
, but what happens in the case that I pass an immutable reference? What compiler rules apply? Does val
remain unchanged even though I'm passing a pointer to the local variable?
I'd say undefined behavior:
Mutating non-mutable data — that is, data reached through a shared reference or data owned by a let
binding), unless that data is contained within an UnsafeCell<U>
.
And this might include:
- if you use
val
after the FFI-call it might ignore the writes you did (e.g. cached the value in a register or due to constant propagation)
- segfault in FFI because the referenced memory might be read-only
- the write from FFI might show up in seemingly unrelated locations because the compiler reused the memory and assumed it had a well-defined value
- and worse :)