除了安全方法之外,如何强制Rust获取分配的内存的所有权?

问题描述 投票:2回答:1

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分配和释放内存的方式未指定,因此传递给此函数的唯一有效指针是通过Box::into_raw函数从另一个Box中获取的指针。

为避免疑义,上面用于执行内存分配的(实验性)Heap API(自Rust 1.27.0中删除)在其__rust_alloc方法中直接称为alloc,因此ptr不是从Box::into_raw获得的。

是否有效,尽管不支持,将Box::from_raw原始指针传递给新分配的内存,以便Rust获取该内存的所有权并执行其通常的安全和包容检查?特别是,当生成的Box被销毁时,Rust会释放那个内存吗?

如果没有,除了安全方法之外,如何强制Rust除了分配内存的所有权?

pointers memory-management rust heap-memory ownership
1个回答
4
投票

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

不,它无效。

特别是,当生成的Box被销毁时,Rust会释放那个记忆吗?

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

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

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

这些担忧也没有弥补。我有submitted patches to GLib来纠正发生不匹配的分配/解除分配的地方并在野外引起真正的问题。

Rust要分配这样的内存所有权

在原始指针级别,所有权在很大程度上是一种心态,就像在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 progressingBox<T>转换为Box<T, A: Alloc + Default = Global>

怎么能强迫Rust

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


也可以看看:

© www.soinside.com 2019 - 2024. All rights reserved.