Search code examples
rustffi

Modifying content in C function with Rust data produces unknown values


I'm trying to call a C function in Rust, and I met a strange problem. This code reproduces my problem:

C

int t(uint8_t *data){
    *data = 1;
    *(data+1) = 2;
    *(data+2) = 3;
}
// block1
unsafe {
    let data = Vec::with_capacity(1024).as_mut_ptr();
    t(data);
    println!("{:?}", Vec::from_raw_parts(data, 4, 4));
}

// block2
unsafe {
    let mut data: Vec<u8> = Vec::with_capacity(1024);
    let pdata = data.as_mut_ptr();
    t(pdata);
    println!("{:?}", Vec::from_raw_parts(pdata, 4, 4));
}

I expect the output to be [1, 2, 3, 0].

Only "block2" works, "block1" outputs [91, 57, 49, 44]. I have no idea where that comes from.

The most confusing thing is that when I put "block1" after "block2" and run them together, they both output [1, 2, 3, 0] correctly.

What didn't I notice? What's the difference between two blocks?


Solution

  • I believe what is happening here is

    let data = Vec::with_capacity(1024).as_mut_ptr();

    This is ends up producing undefined behavior. Here, the Vec<T> is temporary, and so will deallocate its memory after this line runs, so you're passing in a bad pointer to the C.

    That you get different results when moving code around also seems to imply there's UB here.