Does simultaneously accessing the same variable by immutable and mutable pointers cause UB?

fn foo(v:* mut i32, v1:* const i32){
    unsafe{
       *v = 1;  // #1
       let r = *v1;  // #2
       *v = 2;
       let r2 = *v1;
      assert!(r != r2);
   }
}
fn main(){
  let mut i = 0;
  let v = & mut i as * mut _;
  let v2 = &i as * const _;
  foo(v,v2);
}

I know multiple mutable references to the same variable would cause UB. How about pointers?

Q1:

Does *v or *v1 immediately produce a reference?

Q2:

Does this example cause UB? if #2 were let r = *(v1 as * const u8), would it be UB?

Your code has serial accesses, not simultaneous ones. (Data races are always UB.)

Not if you do it right. But under the stacked borrows model, your code is UB because when you made &i to create v2, you invalidated v. (Miri will tell you this[1] by the way.) Instead you should create v2 from v. In general if you're starting from a reference, you should create one raw pointer from a reference with with sufficient permission for everything, and then create all other raw pointers from that one (transitively).

No.

It doesn't compile with that change. But if the *v1 is sound, the *(v1 as *const u8) is sound. (If the type of v1 was different, that might not be true.)


  1. under Tools, top-right ↩ī¸Ž

6 Likes

Nit: raw reference syntax was recently stabilized, and references are best avoided entirely when working with pointers. So the best way to write this example would be

let v = &raw mut i;
let v2 = v as *const _;
8 Likes

Since Rust has introduced & raw to acquire raw pointer after 1.82 version, I wonder whether the following example makes the previously acquired pointer invalid?

let v = &raw mut i;
let v2 = &raw const i;

Does v2 make v invalid like if we use &?

I think creating the pointer doesn't, but the actual accesses do. See my post on IRLO.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.