Why does alloc return u8?

I am confused why the pointers of variables allocated on the stack have the type itself, meanwhile dynamically allocated variables have a u8?

fn main() {
    let mut number: i32 = 25;
    let raw_pointer: *mut i32 = &mut number as *mut i32; // type of the pointer is *mut i32

    unsafe {
        println!("{}", *raw_pointer);
    }
}

but dynamically allocating it would be a pointer of type u8.

    unsafe {
        let layout: Layout = Layout::new::<i32>();
        let raw_pointer: *mut u8 = alloc(layout); // type of the pointer is *mut u8
        
        *raw_pointer = 50;

        println!("{}", *raw_pointer);
    }

The raw allocator API needed to use some type, and they went with u8. You are supposed to cast the raw pointer to the type you want.

Wow, thank you for the really quick response!
So, instead of

 *raw_pointer = 50;
*(raw_pointer as *mut i32) = 50?

Sure, that would work. Though I would typically cast it a bit earlier:

unsafe {
    let layout: Layout = Layout::new::<i32>();
    let raw_pointer = alloc(layout) as *mut i32;

    *raw_pointer = 50;

    println!("{}", *raw_pointer);
}
3 Likes

But this doesn't play well when deallocating?

Would you simply cast it back to u8 when deallocating?

        dealloc(raw_pointer as *mut u8, layout);

Yep, just cast it back.

4 Likes

Just in case anyone isn't aware, Rust has the Box type that can handle dynamic allocations for you without having to do it manually. It's usually the preferred way to allocate on the heap unless you're doing something it (or Vec) can't handle.

9 Likes