pointers - 如何强制 Rust 获得非安全方法分配的内存的所有权?

标签 pointers memory-management rust heap-memory ownership

Will Crichton 在他 2018 年 2 月题为“Memory Safety in Rust: A Case Study with C”的笔记中写道:

Rust provides the ability to take ownership of raw pointers, which we do using slice::from_raw_parts_mut and Box::from_raw which tells Rust to treat the memory pointer as a heap-allocated array. After transferring ownership, assuming the memory is valid and of the right size/type, Rust applies its usual memory safety and containment checks.

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

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 的文档状态(添加了强调):

Since the way Box allocates and releases memory is unspecified, the only valid pointer to pass to this function is the one taken from another Box via the Box::into_raw function.

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

将指向新分配内存的原始指针传递给 Box::from_raw 以使 Rust 取得该内存的所有权并执行其通常的安全和包含检查是否有效(尽管不受支持)?特别是,当出现的 Box 被销毁时,Rust 会释放该内存吗?

如果不是,那么如何强制 Rust 取得这种非安全方法分配的内存所有权?

最佳答案

Is it valid, albeit unsupported, to pass to Box::from_raw raw pointers to freshly allocated memory

不,这是无效的。

In particular, will Rust deallocate that memory when the arising Box is destroyed?

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

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

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

这些担忧也不是虚构的。我有 submitted patches to GLib纠正发生分配/释放不匹配并导致实际问题的地方。

Rust to take such ownership of memory allocated

在原始指针级别,所有权在很大程度上是一种心态,就像在 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可能还有许多其他特性,因此这种类型符合人体工程学。

创建 MallocBox 会很烦人和 JeMallocBox和一个 MyCustomAllocBox ,这就是为什么 RFC 1398为分配器提出共享特征。相关work is progressing转换 Box<T>进入Box<T, A: Alloc + Default = Global> .

how can one force Rust

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


另见:

关于pointers - 如何强制 Rust 获得非安全方法分配的内存的所有权?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54849928/

相关文章:

c - 分散二维数组到连续二维数组的转换(C语言)

rust - 如何将切片的每个元素作为单独的参数传递给可变参数 C 函数?

c - 对所有行的一个 malloc 调用如何为二维数组工作?

c - 如何使两个在其他方面相同的指针类型不兼容

c++ - 这是一个真正的问题 : warning C4172: returning address of local variable or temporary

c++ - C++ 中的指针,原始内存操作

java |垃圾收集器如何忽略没有引用的数组内存

c - Malloc 和 Realloc 的关系,当所需空间在内存中不可用时如何处理

ios - 无法为 iOS 工具链的自定义构建覆盖 Rustup 工具链

macos - 为什么这个 OpenGL 应用程序在某些 Mac 上运行得非常慢?