I noticed that *mut [T]
has a len()
method. So it means that *mut [T]
expects pointer to some memory location that contains both array length and the actual array, right? Therefore I cannot simply cast between the two types? Or is *mut [T]
a fat pointer (so length is not stored behind the pointer but rather is part of the pointer)? Is this for example legal?
let l = Layout::array::<T>(size).unwrap();
let a = std::alloc::alloc(new_layout) as *mut [T];
Or should I use *mut T
?
[T]
is a dynamically sized type (DST). Pointers to DSTs are fat pointers that include the length, as you already suspected.
Your example (simplified to use i32
instead of T
)
fn main() {
let l = std::alloc::Layout::array::<i32>(10).unwrap();
let a = std::alloc::alloc(l) as *mut [i32];
}
will fail at compile time, with the following, very helpful error:
error[E0607]: cannot cast thin pointer `*mut u8` to fat pointer `*mut [i32]`
--> src/main.rs:5:9
|
5 | let a = std::alloc::alloc(l) as *mut [i32];
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For more information about this error, try `rustc --explain E0607`.
Which neatly proves this point.
An example to create a slice from a thin pointer could look like this:
fn main() {
let layout = std::alloc::Layout::array::<i32>(10).unwrap();
let slice = unsafe {
let ptr = std::alloc::alloc(layout) as *mut i32;
std::ptr::write_bytes(ptr, 0u8, 10); // initialize memory
std::slice::from_raw_parts(ptr, 10)
};
println!("{:?}", slice);
}