Can I hold a pointer (unsafely) to an element of Vec while the Vec is being moved?

Viewed 129

I'm implementing an algorithm, and in order to maintain the desired time complexity, I would like to hold a pointer to an element of a Vec while the Vec is being moved.

Specifically, something like this:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3];
    let ptr: *mut usize = &mut v[1] as *mut usize;
    let mut u: Vec<usize> = v;
    assert!(ptr == &mut u[1] as *mut usize);
    println!("{}", unsafe { *ptr });
}

The actual code is more complicated, and involves a tree-like data structure where each vertex owns a Vec of children. I'm not asking about coding style here, but my question is about whether this code can be relied on to do what I think it does.

Since Vec has to hold its content on the heap, and moves are equivalent to memcpy in Rust, I think the fact that Vec is movable would imply that my code is sound (i.e. not undefined behaviour). Is this correct?

1 Answers

You can do it like this:

fn main() {
    let mut v: Vec<usize> = vec![1, 2, 3];
    let ptr: *mut usize = &mut v[1] as *mut usize;
    let mut u: Vec<usize> = v;
    assert!(ptr == &mut u[1] as *mut usize);
    // I copied this from Stack Overflow without reading the surrounding prose 
    println!("{}", unsafe { *ptr });
}

You should document the unsafe block with exactly what the safety conditions are and how you are upholding them. In this case...

  1. The Vec's elements are heap-allocated:

    If a Vec has allocated memory, then the memory it points to is on the heap

  2. You have not changed the backing allocation during the time of the move. This could be due to any modification of the Vec that results in a resize or destruction.

  3. No aliasing reference to the same element (including anything that could reach the same element) exists when you try to use the reference.


For this example, I'd just use an index (1). For your tree case, I'd try to use a vector of indices. Benchmark to see if there's a noticeable difference.

Related