fn get_base_ptr(len : usize) -> *mut u8
{
let mut buf: Vec<u8> = Vec::with_capacity(len);
let ptr : *mut u8 = buf.as_mut_ptr();
std::mem::forget(ptr);
return ptr;
}
fn sum(buf_ptr : *mut u8) -> ()
{
unsafe {
let data = Vec::from_raw_parts(buf_ptr, 16, 16);
let sum: u8 = data.iter().sum();
println!("Sum is {}", sum);
}
}
fn main()
{
let input = vec![1 as u8, 2, 3, 4, 5];
for i in 1 .. 2 {
let buf_ptr = get_base_ptr(input.len());
unsafe {
std::ptr::copy(input.as_ptr(), buf_ptr, input.len());
sum(buf_ptr);
}
}
}
It runs and then spits out the following:
mem(20659,0x10cce1dc0) malloc: *** error for object 0x7f952d405c50: pointer being freed was not allocated
mem(20659,0x10cce1dc0) malloc: *** set a breakpoint in malloc_error_break to debug
Abort trap: 6
First issue: in get_base_ptr, you're forgetting ptr, not buf, so buf gets de-allocated at the end of the function and the pointer you return is dangling. This causes undefined behaviour when you try to use that pointer later on, because the thing it was pointing at no longer exists.
Second issue: in sum, you're saying buf_ptr points at a Vec with capacity 16 and length 16, when it actually points at a Vec with capacity 5 and (since you've initialized it via the std::ptr::copy) length 5. This causes undefined behaviour when you try to sum data, because you're reading uninitialized memory.
Fixing these two issues gets Miri (a Rust interpreter that can detect some cases of undefined behaviour) to stop complaining, but I'm not confident enough in my unsafe knowledge to know if there's not other UB lurking here.
To add to what @17cupsofcoffee said, here's how I'd rewrite this code with no unsafe:
fn main() {
let input = vec![1u8, 2, 3, 4, 5];
// `Vec::leak` "forgets" the vector and returns a `&[T]` of its contents
let slice: &'static [u8] = input.leak();
dbg!(slice.iter().sum());
}