威尔·克里顿(Will Crichton)在2018年2月的便条“Memory Safety in Rust:A Case Study with C”中写道:
上面提到的他的代码的相关部分是:
let mut new_data = unsafe {
let ptr = Heap::default()
.alloc(Layout::array::<isize>(new_capacity).unwrap())
.unwrap() as *mut isize;
Box::from_raw(slice::from_raw_parts_mut(ptr, new_capacity))
};
但是,
Box::from_raw
的文档说明了(强调):为避免疑问,上面用于执行内存分配(从Rust 1.27.0中删除)的(实验性)
Heap
API在其 __rust_alloc
方法中直接称为alloc
,因此未从ptr
获得Box::into_raw
。尽管不支持,将
Box::from_raw
原始指针传递给新分配的内存是否有效,以使Rust拥有该内存的所有权并执行其通常的安全性和遏制性检查?特别是,当出现的Box被销毁时,Rust是否会重新分配该内存?如果不是,除了强制使用安全方法外,如何迫使Rust拥有这样分配的内存所有权?
最佳答案
不,这是无效的。
是的,这就是它无效的原因。
内存分配器提供配对的分配和释放例程。当使用一个分配器分配一块内存时,必须使用该分配器释放它。
如果不这样做,那么当进行分配的分配器执行其需要做的任何簿记操作时,它就不会知道那部分内存。实际进行分配的分配器永远不会将该内存标记为不可用。
这些问题也没有得到解决。我使用submitted patches to GLib来纠正发生分配/释放分配不匹配并在野外引起实际问题的地方。
就原始指针而言,所有权在很大程度上是一种心态,就像在C或C++中一样。在这里拥有东西意味着您有责任适当地清理它。malloc
和free
是成对的分配/取消分配方法。您可以创建自己的类型并为其实现Drop
:
use libc::{free, malloc};
use std::{ffi::c_void, mem};
struct MallocBox(*mut i32);
impl MallocBox {
fn new(v: i32) -> Self {
unsafe {
let p = malloc(mem::size_of::<i32>()) as *mut i32;
*p = v;
Self(p)
}
}
}
impl Drop for MallocBox {
fn drop(&mut self) {
unsafe { free(self.0 as *mut c_void) }
}
}
fn main() {
MallocBox::new(42);
}
真正的实现还可以实现
Deref
以及可能的许多其他特征,以便使用这种类型的人体工程学。必须创建
MallocBox
和JeMallocBox
以及MyCustomAllocBox
会很烦人,这就是RFC 1398为分配器提出共享特征的原因。相关的work is progressing将Box<T>
转换为Box<T, A: Alloc + Default = Global>
。没有“强制” Rust做任何事情的概念,更不用说像这样的低级细节了。例如,不能保证分配指针的C代码不会尝试释放指针本身。在FFI世界中,所有权是一种合作协议(protocol)。
也可以看看: