Function sp_std::ptr::drop_in_place

1.8.0 · source ·
pub unsafe fn drop_in_place<T>(to_drop: *mut T)where
    T: ?Sized,
Expand description

Executes the destructor (if any) of the pointed-to value.

This is semantically equivalent to calling ptr::read and discarding the result, but has the following advantages:

  • It is required to use drop_in_place to drop unsized types like trait objects, because they can’t be read out onto the stack and dropped normally.

  • It is friendlier to the optimizer to do this over ptr::read when dropping manually allocated memory (e.g., in the implementations of Box/Rc/Vec), as the compiler doesn’t need to prove that it’s sound to elide the copy.

  • It can be used to drop pinned data when T is not repr(packed) (pinned data must not be moved before it is dropped).

Unaligned values cannot be dropped in place, they must be copied to an aligned location first using ptr::read_unaligned. For packed structs, this move is done automatically by the compiler. This means the fields of packed structs are not dropped in-place.

Safety

Behavior is undefined if any of the following conditions are violated:

  • to_drop must be valid for both reads and writes.

  • to_drop must be properly aligned.

  • The value to_drop points to must be valid for dropping, which may mean it must uphold additional invariants - this is type-dependent.

Additionally, if T is not Copy, using the pointed-to value after calling drop_in_place can cause undefined behavior. Note that *to_drop = foo counts as a use because it will cause the value to be dropped again. write() can be used to overwrite data without causing it to be dropped.

Note that even if T has size 0, the pointer must be non-null and properly aligned.

Examples

Manually remove the last item from a vector:

use std::ptr;
use std::rc::Rc;

let last = Rc::new(1);
let weak = Rc::downgrade(&last);

let mut v = vec![Rc::new(0), last];

unsafe {
    // Get a raw pointer to the last element in `v`.
    let ptr = &mut v[1] as *mut _;
    // Shorten `v` to prevent the last item from being dropped. We do that first,
    // to prevent issues if the `drop_in_place` below panics.
    v.set_len(1);
    // Without a call `drop_in_place`, the last item would never be dropped,
    // and the memory it manages would be leaked.
    ptr::drop_in_place(ptr);
}

assert_eq!(v, &[0.into()]);

// Ensure that the last item was dropped.
assert!(weak.upgrade().is_none());