Rust 中的精确内存布局控制?

Posted

技术标签:

【中文标题】Rust 中的精确内存布局控制?【英文标题】:Precise memory layout control in Rust? 【发布时间】:2014-12-03 22:54:38 【问题描述】:

据我所知,Rust 编译器允许对结构的每个字段进行打包、重新排序和添加填充。如果需要,如何指定精确的内存布局?

在 C# 中,我有 StructLayout 属性,在 C/C++ 中,我可以使用各种编译器扩展。我可以通过检查期望值位置的字节偏移来验证内存布局。

我想编写使用自定义着色器的 OpenGL 代码,这需要精确的内存布局。有没有办法在不牺牲性能的情况下做到这一点?

【问题讨论】:

【参考方案1】:

如the FFI guide 中所述,您可以向结构添加属性以使用与 C 相同的布局:

#[repr(C)]
struct Object 
    a: i32,
    // other members

你还可以打包结构体:

#[repr(C, packed)]
struct Object 
    a: i32,
    // other members

为了检测内存布局是否正常,您可以初始化一个结构并通过将指针转换为整数来检查偏移量是否正常:

#[repr(C, packed)]
struct Object 
    a: u8,
    b: u16,
    c: u32, // other members


fn main() 
    let obj = Object 
        a: 0xaa,
        b: 0xbbbb,
        c: 0xcccccccc,
    ;
    let a_ptr: *const u8 = &obj.a;
    let b_ptr: *const u16 = &obj.b;
    let c_ptr: *const u32 = &obj.c;

    let base = a_ptr as usize;

    println!("a: ", a_ptr as usize - base);
    println!("b: ", b_ptr as usize - base);
    println!("c: ", c_ptr as usize - base);

输出:

a: 0
b: 1
c: 3

【讨论】:

【参考方案2】:

不再有to_uint。在 Rust 1.0 中,代码可以是:

#[repr(C, packed)]
struct Object 
    a: i8,
    b: i16,
    c: i32, // other members


fn main() 
    let obj = Object 
        a: 0x1a,
        b: 0x1bbb,
        c: 0x1ccccccc,
    ;

    let base = &obj as *const _ as usize;
    let a_off = &obj.a as *const _ as usize - base;
    let b_off = &obj.b as *const _ as usize - base;
    let c_off = &obj.c as *const _ as usize - base;

    println!("a: ", a_off);
    println!("b: ", b_off);
    println!("c: ", c_off);

【讨论】:

【参考方案3】:

你也可以像这样为“data-carrying enums”设置内存布局。

#[repr(Int)]
enum MyEnum 
    A(u32),
    B(f32, u64),
    C  x: u32, y: u8 ,
    D,

详细信息在手册和 RFC2195 中有描述。

https://rust-lang.github.io/unsafe-code-guidelines/layout/enums.html https://rust-lang.github.io/rfcs/2195-really-tagged-unions.html#motivation

【讨论】:

以上是关于Rust 中的精确内存布局控制?的主要内容,如果未能解决你的问题,请参考以下文章

C中的结构内存布局

从内存布局上看,Rust的胖指针到底胖在栈上还是堆上?

浅析C++内存布局

Linux进程地址空间与进程内存布局详解,内核空间与用户空间

Rust 内存管理

Rust 内存安全指南