Skip to content

Vec::from_raw_parts

Vec methods · Collections

Level: reference · for working programmers

One line: Rebuild a Vec from a pointer, a length and a capacity.

pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec<T>

Stable since 1.0.0. Its const form is still unstable.

The unsafe counterpart of into_raw_parts, and the conditions are strict enough that the only reliably correct source of the three numbers is a Vec that produced them:

  • ptr must come from a Vec (or the same global allocator) with the same T — the size and alignment are used to compute the deallocation
  • capacity must be the capacity the buffer was allocated with, not the length
  • the first length elements must be initialised
  • length <= capacity

Getting capacity wrong corrupts the allocator. Getting T wrong is worse.

Lowering the length on the way back in is allowed: the elements above it are then leaked rather than dropped, but the buffer is still freed correctly because the capacity is right.

Almost every use has a safe alternative. For a Box<[T]>, Vec::from(boxed) is free and safe. For borrowing a buffer, as_slice. Reach for this only across an FFI boundary where a Vec really was decomposed on the other side.

Example

vec_from_raw_parts.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    // The only reliably correct source of the three numbers is a Vec that
    // produced them, which is what into_raw_parts is for.
    let original = vec![1u16, 2, 3];
    let (ptr, len, cap) = original.into_raw_parts();

    // Same pointer, same length, same capacity, same T. All four must match.
    let v = unsafe { Vec::from_raw_parts(ptr, len, cap) };
    println!("round trip: {v:?}");

    // Length may be lowered on the way back in — the elements above it are
    // then leaked rather than dropped, but the buffer is still freed correctly
    // because the capacity is right.
    let (ptr, _len, cap) = v.into_raw_parts();
    let shorter = unsafe { Vec::from_raw_parts(ptr, 2, cap) };
    println!("rebuilt with len 2 of 3: {shorter:?} cap {}", shorter.capacity());
    drop(shorter);

    // Building one from a Box<[T]> is the safe way to do the same thing, and
    // is what you almost always actually want.
    let boxed: Box<[u16]> = Box::new([7, 8, 9]);
    let from_box: Vec<u16> = boxed.into();
    println!("Vec::from(Box<[T]>): {from_box:?} cap {}", from_box.capacity());

    // A Vec's own buffer, borrowed rather than taken — no unsafe needed.
    let borrow = vec![4u16, 5];
    println!("as_slice instead: {:?}", borrow.as_slice());
}

Verified output of vec_from_raw_parts.rs — regenerated by tools/run_examples.py, never hand-typed.

round trip: [1, 2, 3]
rebuilt with len 2 of 3: [1, 2] cap 3
Vec::from(Box<[T]>): [7, 8, 9] cap 3
as_slice instead: [4, 5]

See also

Vec::from_raw_parts in the standard library ↗