[solved] Vec::from_raw_parts got SIGSEGV when run in another thread

Hi,

I write a code to call a C function from Rust, that function return a pointer to an integer array allocated on heap. To use that array in Rust, I wrapped it using Vec::from_raw_parts. It is fine if I run it in the main thread, however, when I run it in another thread, I got SIGSEGV. Here is a minimum code to re-produce it.

fn test() {
    unsafe {
        let numbers: *mut i32 = libc::malloc(std::mem::size_of::<i32>() * 5) as *mut i32;
        for i in 0..5 as isize {
            std::ptr::write(numbers.offset(i), 10 * i as i32);
        }

        let x = Vec::from_raw_parts(numbers, 5, 5);
        println!("x = {:?}", x);
    }
}


fn main() {
    test();
    println!("before spawn new thread");
    let handle = thread::spawn(|| {
        test();
        println!("TERMINATE");
    });
    handle.join().unwrap();

    println!("FINISH!!!!");
}

Output:

x = [0, 10, 20, 30, 40]
before spawn new thread
x = [0, 10, 20, 30, 40]

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

What did I do wrong and how to fix it?

Thanks!

You need to be using libc::free since languages use different allocators.
Also; (p.s. don't have much personal experience)
Should check malloc doesn't fail; return null pointer.
Using from_raw_parts_mut probablly better than Vec.

3 Likes

Notice this part of the documentation:

Vec in std::vec - Rust regarding from_raw_parts:

ptr needs to have been previously allocated via String/Vec (at least, it's highly likely to be incorrect if it wasn't).

2 Likes

Yes, definitely use slice, not Vec. Vec assumes that the memory was allocated by Vec, and it needs that guarantee when resizing.

2 Likes

Thank you all for your help!

I definitely missed that in the documentation. I change from vec to slice and it works just fine.

1 Like