rust - 如何向/从 NonNull<Opaque> 添加/减去偏移量?

标签 rust

我提供了两个管理内存的函数:

unsafe extern "system" fn alloc<A: Alloc>(
    size: usize,
    alignment: usize,
) -> *mut c_void { ... }

unsafe extern "system" fn free<A: Alloc>(
    memory: *mut c_void
) { ... }

这两个函数在内部都使用 allocator-api .

这些签名无法更改。问题是 free不要求 sizealignment ,这是 Alloc::dealloc 所必需的.为了解决这个问题,alloc为一个 Layout 分配一些额外空间. free现在可以访问这个 Layout获取所需的额外数据。

最近,allocator-api改变了而不是*mut u8它现在使用 NonNull<Opaque> .这是我的问题发生的地方。

core::alloc::Opaque :

An opaque, unsized type. Used for pointers to allocated memory. [...] Such pointers are similar to C’s void* type.

Opaque不是 Sized , 所以使用 NonNull::as_ptr().add()NonNull::as_ptr().sub()被禁止。

以前,我使用过类似的东西(为简单起见,我假设 Alloc 的函数是静态的):

#![feature(allocator_api)]
#![no_std]

extern crate libc;

use core::alloc::{Alloc, Layout};
use libc::c_void;

unsafe extern "system" fn alloc<A: Alloc>(
    size: usize,
    alignment: usize,
) -> *mut c_void
{
    let requested_layout =
        Layout::from_size_align(size, alignment).unwrap();

    let (layout, padding) = Layout::new::<Layout>()
        .extend_packed(requested_layout)
        .unwrap();

    let ptr = A::alloc(layout).unwrap(); 
    (ptr as *mut Layout).write(layout);
    ptr.add(padding)
}

NonNull<Opaque> 不再可能最后一行.我该如何解决这个问题?

最佳答案

我可能会这样写,使用 NonNull::as_ptr 得到 *mut Opaque然后将其转换为不同的具体类型:

#![feature(allocator_api)]
#![no_std]

extern crate libc;

use core::alloc::{Alloc, Layout};
use libc::c_void;

unsafe fn alloc<A: Alloc>(allocator: &mut A, size: usize, alignment: usize) -> *mut c_void {
    let requested_layout = Layout::from_size_align(size, alignment).expect("Invalid layout");

    let (layout, _padding) = Layout::new::<Layout>()
        .extend_packed(requested_layout)
        .expect("Unable to create layout");

    let ptr = allocator.alloc(layout).expect("Unable to allocate");

    // Get a pointer to our layout storage 
    let raw = ptr.as_ptr() as *mut Layout;
    // Save it
    raw.write(layout);
    // Skip over it
    raw.offset(1) as *mut _
}

unsafe extern "system" fn alloc<A: Alloc>(

这对我来说毫无意义。各种 FFI ABI(“C”、“系统”等)无法指定 Rust 泛型类型。将此功能标记为 extern 似乎非常不正确.


Layout::new::<Layout>().extend_packed(requested_layout)

这看起来很可能被破坏了。作为documentation for Layout::extend_packed 状态,强调我的:

the alignment of next is irrelevant, and is not incorporated at all into the resulting layout.

您返回的指针似乎不符合对齐请求。

关于rust - 如何向/从 NonNull<Opaque> 添加/减去偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50373726/

相关文章:

rust - 如何使用方法 "UnicodeSegmentation::graphemes"

rust - Rust 中 libc::stat 中的文件参数

azure - 使用 Azure Monitor 数据收集器 API 时授权 header 中的签名无效

scala - 如何将 Scala 匿名特征实现转换为 Rust?

rust - Rust 的借用检查器在这里真正提示的是什么?

rust - 如何从 std::io::Error 获取消息字符串?

python - Python神经网络代码的Rust实现

Rust/rocket 将变量传递到端点

string - 我应该实现 Display 还是 ToString 来将类型呈现为字符串?

Rust 模块,结合两个 use 语句