使用slice::from_raw_parts_mut和ptr::drop_in_place in rust进行内存释放

使用slice::from_raw_parts_mut和ptr::drop_in_place in rust进行内存释放,rust,slice,Rust,Slice,我在网上看到一段代码,它使用std::slice::from_raw_parts_mut()和std::ptr::drop_in_place()的组合删除分配的内存。下面是一段代码,分配一个由十个整数组成的数组,然后对其进行反分配: use std::{ alloc::{alloc, Layout}, ptr::NonNull, }; fn main() { let len: usize = 10; let layout: Layout = Layout::ar

我在网上看到一段代码,它使用
std::slice::from_raw_parts_mut()
std::ptr::drop_in_place()
的组合删除分配的内存。下面是一段代码,分配一个由十个整数组成的数组,然后对其进行反分配:

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));
    }
}
使用std::{
alloc::{alloc,Layout},
ptr::非空,
};
fn main(){
设len:usize=10;
let layout:layout=layout::array::(len).unwrap();
let data:NonNull=unsafe{NonNull::new(alloc(layout)as*mut i32).unwrap()};
不安全{
std::ptr::drop_in_place(std::slice::from_raw_parts_mut(data.as_ptr(),len));
}
}

std::slice::from_raw_parts_mut()
的返回类型是一个可变片
&mut[T]
,但是
std::ptr::drop_in_place()
的参数是
*mut
。在我看来,转换是自动进行的。我很确定我错过了什么,因为这是不允许的。有人能解释一下这里到底发生了什么吗?

当您编写
std::slice::from_raw_parts_mut(data.as_ptr(),len)
时,您正在构建
&mut[i32]
类型的值

然后将其传递给
drop\u in\u place()
,它或多或少定义为:

fn drop_in_place<T: ?Sized>(to_drop: *mut T)
fn放置到位(放置:*mut T T)
因此,您正在将一个
&mut[i32]
强制为一个
*mut
,这可以通过两个步骤来解决:有一个来自的自动强制,然后
T
被解析为
[i32]
,这是实际调用
drop
的类型

(您可能认为从引用到指针的自动强制是危险的,不应该是自动的,但实际上是完全安全的。不安全的通常是您事后对指针所做的操作。实际上,原始指针有两种安全的用法,例如
std::ptr::eq
std::ptr::hash

切片通过简单地迭代元素并在每个元素中调用
Drop\in\u place
来实现
Drop::Drop
。这是一种避免手动编写循环的聪明方法

但请注意关于此代码的几点:

  • drop\u in_place
    将在片的每个元素上调用
    drop::drop
    ,但由于它们属于
    i32
    类型,因此实际上是禁止操作的。我猜您的原始代码使用了泛型类型
  • drop\u in\u place
    不会释放内存,因此需要调用
    std::alloc::dealloc

  • 实际上,有一个从
    &mut[T]
    *mut[T]
    的转换。你认为这段代码的哪一步应该失败?@rodrigo将
    &mut[T]
    隐式转换为
    *mut[T]
    。我是个新手,但我找不到任何提到这种隐式转换的文档。还请注意,在本例中,转换是从
    &mut[T]
    *mut[T
    的转换,而不是您提到的(
    &mut[T]
    *mut[T]
    )从引用到原始指针的隐式转换(强制)。我认为你错了:
    drop\u in_place()
    采用
    *mut
    但是
    T
    是从上下文自动推导出来的,如果你传入
    &mut[i32]
    ,那么
    T
    将解析为
    [i32]
    ,因此你正在从
    &mut[i32]
    转换为
    *mut[i32]
    @rodrigo你能写一个答案让我接受吗。