W3cubDocs

/Rust

Function std::ptr::drop_in_place

pub unsafe fn drop_in_place<T>(to_drop: *mut T) where    T: ?Sized, 

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., when writing Box/Rc/Vec), as the compiler doesn't need to prove that it's sound to elide the copy.

Safety

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

  • to_drop must be valid for reads.

  • to_drop must be properly aligned. See the example below for how to drop an unaligned pointer.

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());

Unaligned values cannot be dropped in place, they must be copied to an aligned location first:

use std::ptr;
use std::mem::{self, MaybeUninit};

unsafe fn drop_after_copy<T>(to_drop: *mut T) {
    let mut copy: MaybeUninit<T> = MaybeUninit::uninit();
    ptr::copy(to_drop, copy.as_mut_ptr(), 1);
    drop(copy.assume_init());
}

#[repr(packed, C)]
struct Packed {
    _padding: u8,
    unaligned: Vec<i32>,
}

let mut p = Packed { _padding: 0, unaligned: vec![42] };
unsafe {
    drop_after_copy(&mut p.unaligned as *mut _);
    mem::forget(p);
}

Notice that the compiler performs this copy automatically when dropping packed structs, i.e., you do not usually have to worry about such issues unless you call drop_in_place manually.

© 2010 The Rust Project Developers
Licensed under the Apache License, Version 2.0 or the MIT license, at your option.
https://doc.rust-lang.org/std/ptr/fn.drop_in_place.html