除了安全方法外,如何迫使Rust占有已分配内存的所有权?

时间:2019-02-24 08:01:34

标签: pointers memory-management rust heap-memory ownership

威尔·克里顿(Will Crichton)在2018年2月的题为“ Memory Safety in Rust: A Case Study with C”的笔记中写道:

  

Rust提供了获取原始指针所有权的能力,我们使用slice::from_raw_parts_mutBox::from_raw进行操作,这告诉Rust将内存指针视为堆分配的数组。转移所有权后,假设内存有效且具有正确的大小/类型,Rust将应用其通常的内存安全性和包含性检查。

上面提到的他的代码的相关部分是:

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的文档说明了(强调):

  

由于未指定Box分配和释放内存的方式, 传递给该函数的唯一有效指针 是通过{{3}从另一个Box获取的指针}功能。

为免生疑问,上面使用的(实验性)Box::into_raw API在其Heap方法中直接调用了__rust_alloc来执行内存分配(从Rust 1.27.0中删除)。因此不是ptr获得的。{p>

传递给Box::into_raw原始指针到新分配的内存,以使Rust拥有该内存的所有权并执行其通常的安全性和遏制性检查,是否有效?特别是,当出现的Box被销毁时,Rust是否会重新分配该内存?

如果没有, 怎么能迫使Rust拥有这种通过安全方法分配的内存所有权?

1 个答案:

答案 0 :(得分:4)

  

传递给Box::from_raw原始指针到新分配的内存是否有效,尽管不受支持

否,它无效。

  

尤其是当出现的Box被销毁时,Rust是否会重新分配该内存?

是的,这就是它无效的原因。

内存分配器提供了成对分配和释放例程。当您使用一个分配器分配一块内存时,您必须使用该分配器释放它

如果不这样做,那么当进行分配的分配器执行其需要做的任何簿记操作时,它将不知道那部分内存。实际进行分配的分配器永远不会将该内存标记为不可用。

这些问题也没有得到解决。我已经submitted patches to GLib纠正了分配/解除分配不匹配并在野外引起实际问题的地方。

  

必须拥有分配的内存的所有权

就原始指针而言,所有权在很大程度上是一种心态,就像在C或C ++中一样。在这里拥有自己的东西意味着您有责任适当地清理它。

mallocfree是成对的分配/解除分配方法。您可以创建自己的类型并为其实现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以及可能的许多其他特征,以便使用这种类型的人体工程学。

必须创建一个MallocBoxJeMallocBox和一个MyCustomAllocBox会很烦人,这就是RFC 1398为分配器提出一个共享特征的原因。与work is progressing相关,将Box<T>转换为Box<T, A: Alloc + Default = Global>

  

一个人怎么能生锈

没有“强制” Rust做任何事情的概念,更不用说像这样的低级细节了。例如,不能保证分配指针的C代码不会尝试释放指针本身。在FFI世界中,所有权是一种合作协议。


另请参阅: