简体   繁体   English

Memory 在 rust 中使用 slice::from_raw_parts_mut 和 ptr::drop_in_place 解除分配

[英]Memory deallocation using slice::from_raw_parts_mut and ptr::drop_in_place in rust

I saw a piece of code online that was dropping allocated memory using a combination of std::slice::from_raw_parts_mut() and std::ptr::drop_in_place() .我在网上看到一段代码使用std::slice::from_raw_parts_mut()std::ptr::drop_in_place()组合删除分配的 memory 。 Below is a piece of code that allocates an array of ten integers and then de-allocates it:下面是一段代码,它分配了一个由十个整数组成的数组,然后取消分配它:

use std::{
    alloc::{alloc, Layout},
    ptr::NonNull,
};

fn main() {
    let len: usize = 10;
    let layout: Layout = Layout::array::<i32>(len).unwrap();
    let data: NonNull<i32> = unsafe { NonNull::new(alloc(layout) as *mut i32).unwrap() };

    unsafe {
        std::ptr::drop_in_place(std::slice::from_raw_parts_mut(data.as_ptr(), len));
    }
}

The return type of std::slice::from_raw_parts_mut() is a mutable slice &mut [T] , but the argument of std::ptr::drop_in_place() is *mut T . std::slice::from_raw_parts_mut()的返回类型是可变切片&mut [T] ,但std::ptr::drop_in_place()的参数是*mut T It seems to me that the conversion happens automatically.在我看来,转换是自动发生的。 I'm pretty sure I'm missing something here since it shouldn't be allowed.我很确定我在这里遗漏了一些东西,因为它不应该被允许。 Would someone explain what exactly is happening here?有人会解释这里到底发生了什么吗?

When you write std::slice::from_raw_parts_mut(data.as_ptr(), len) you are building a value of type &mut [i32] .当您编写std::slice::from_raw_parts_mut(data.as_ptr(), len)时,您正在构建一个&mut [i32]类型的值。

Then you are passing it to drop_in_place() that is defined more or less as:然后你将它传递给drop_in_place()或多或少定义为:

fn drop_in_place<T: ?Sized>(to_drop: *mut T)

So you are coercing a &mut [i32] into a *mut T , that is solved in two steps: there is an automatic coercion from reference to pointer , and then T is resolved as [i32] which is the type whose drop is actually called.因此,您将&mut [i32]转换为*mut T ,这分两步解决:从对指针的引用进行自动强制,然后T被解析为[i32] ,这是实际调用drop的类型.

(You may think that the automatic coercion from reference to pointer is dangerous and should not be automatic, but it is actually totally safe. What is unsafe is usually what you do with the pointer afterwards. And actually there are a couple of uses of raw pointers that are safe, such as std::ptr::eq or std::ptr::hash ). (你可能认为从引用到指针的自动强制是危险的,不应该是自动的,但它实际上是完全安全的。不安全的通常是你之后对指针所做的事情。实际上有几个 raw 的用法安全的指针,例如std::ptr::eqstd::ptr::hash )。

Slices implement Drop::drop by simply iterating over the elements and calling drop_in_place in each of them.切片通过简单地迭代元素并在每个元素中调用drop_in_place来实现Drop::drop This is a clever way to avoid writing the loop manually.这是避免手动编写循环的巧妙方法。

But note a couple of things about this code:但请注意有关此代码的一些事项:

  1. drop_in_place will call Drop::drop on every element of the slice, but since they are of type i32 it is effectively a no-op. drop_in_place将对切片的每个元素调用Drop::drop ,但由于它们是i32类型,因此实际上是无操作的。 I guess that your original code uses a generic type.我猜您的原始代码使用了泛型类型。
  2. drop_in_place does not free the memory, for that you need a call to std::alloc::dealloc . drop_in_place不会释放 memory,因为您需要调用std::alloc::dealloc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM