在 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
我在网上看到一段代码,它使用 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::slice::from_raw_parts_mut()
的return类型是可变切片&mut [T]
,但std::ptr::drop_in_place()
的参数是*mut T
。在我看来,转换是自动发生的。我很确定我在这里遗漏了一些东西,因为它不应该被允许。有人能解释一下这里到底发生了什么吗?
当您编写 std::slice::from_raw_parts_mut(data.as_ptr(), len)
时,您正在构建一个类型为 &mut [i32]
的值。
然后你将它传递给 drop_in_place()
或多或少定义为:
fn drop_in_place<T: ?Sized>(to_drop: *mut T)
所以你将 &mut [i32]
强制转换为 *mut T
,分两步解决:reference to pointer 自动强制转换,然后 T
解析为 [i32]
这是 drop
实际被调用的类型。
(你可能认为从引用到指针的自动强制转换是危险的,不应该是自动的,但实际上它是完全安全的。不安全的通常是你之后对指针所做的事情。实际上有一个一些安全的原始指针的使用,例如 std::ptr::eq
或 std::ptr::hash
).
切片通过简单地遍历元素并在每个元素中调用 drop_in_place
来实现 Drop::drop
。这是避免手动编写循环的聪明方法。
但请注意有关此代码的几件事:
drop_in_place
将在切片的每个元素上调用 Drop::drop
,但由于它们属于 i32
类型,因此实际上是空操作。我猜你的原始代码使用了泛型。
drop_in_place
不会释放内存,为此您需要调用 std::alloc::dealloc
.
我在网上看到一段代码,它使用 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::slice::from_raw_parts_mut()
的return类型是可变切片&mut [T]
,但std::ptr::drop_in_place()
的参数是*mut T
。在我看来,转换是自动发生的。我很确定我在这里遗漏了一些东西,因为它不应该被允许。有人能解释一下这里到底发生了什么吗?
当您编写 std::slice::from_raw_parts_mut(data.as_ptr(), len)
时,您正在构建一个类型为 &mut [i32]
的值。
然后你将它传递给 drop_in_place()
或多或少定义为:
fn drop_in_place<T: ?Sized>(to_drop: *mut T)
所以你将 &mut [i32]
强制转换为 *mut T
,分两步解决:reference to pointer 自动强制转换,然后 T
解析为 [i32]
这是 drop
实际被调用的类型。
(你可能认为从引用到指针的自动强制转换是危险的,不应该是自动的,但实际上它是完全安全的。不安全的通常是你之后对指针所做的事情。实际上有一个一些安全的原始指针的使用,例如 std::ptr::eq
或 std::ptr::hash
).
切片通过简单地遍历元素并在每个元素中调用 drop_in_place
来实现 Drop::drop
。这是避免手动编写循环的聪明方法。
但请注意有关此代码的几件事:
drop_in_place
将在切片的每个元素上调用Drop::drop
,但由于它们属于i32
类型,因此实际上是空操作。我猜你的原始代码使用了泛型。drop_in_place
不会释放内存,为此您需要调用std::alloc::dealloc
.