【问题标题】:Correct idiom for freeing repr(C) structs using Drop trait使用 Drop trait 释放 repr(C) 结构的正确习惯用法
【发布时间】:2015-06-09 20:16:37
【问题描述】:

这段代码运行良好,但在 Rust nightly (1.2) 上会给出编译器警告

#[repr(C)]
struct DbaxCell { 
    cell: *const c_void
}

#[link(name="CDbax", kind="dylib")] 
extern {
    fn new_dCell(d: c_double) -> *const c_void;
    fn deleteCell(c: *const c_void);
}

impl DbaxCell {
    fn new(x: f64) -> DbaxCell {
        unsafe {
            DbaxCell { cell: new_dCell(x) }
        }
    }
}

impl Drop for DbaxCell {
    fn drop(&mut self) {
        unsafe {
            deleteCell(self.cell);
        }
    }
}

它链接到 C 库并正确创建/删除单元对象。但是它会发出警告

src\lib.rs:27:1: 33:2 warning: implementing Drop adds hidden state to types, possibly conflicting with `#[repr(C)]`, #[warn(drop_with_repr_extern)] on by default
\src\lib.rs:27 impl Drop for DbaxCell {
\src\lib.rs:28     fn drop(&mut self) {
\src\lib.rs:29         unsafe {
\src\lib.rs:30             deleteCell(self.cell);
\src\lib.rs:31         }
\src\lib.rs:32     }

确保正确清理这些DbaxCells 并且不发出警告的正确方法是什么?

【问题讨论】:

    标签: c memory rust


    【解决方案1】:

    我认为您将两个概念混为一谈。如果您希望结构的布局直接对应到结构的布局,则结构应该是repr(C),因为 C 编译器会对其进行布局。也就是说,它具有相同的内存中representation。

    但是,如果您只是持有一个原始指针,并且不打算将持有结构传递回 C,那么您不需要。在这种情况下,简短的解决方案是“删除 @ 987654327@".

    解释一下这个错误...

    实现 Drop 为类型添加隐藏状态,可能与 #[repr(C)] 冲突

    这已在issue 24585 中讨论过。当一个对象被丢弃时,会设置一个隐藏标志(“状态”),指示该对象已被丢弃,从而防止发生多次丢弃。但是,隐藏位意味着您在 Rust 中看到的内容与在 C 中的结构字节不对应,这否定了 repr(C) 的目的。

    作为cribbed from @bluss:

    低级程序员,别担心:future Rust 将完全删除此丢弃标志。

    使用repr(C) 在 FFI 中传递结构,如果需要,在“常规 Rust”结构上使用 Drop。如果两者都需要,请将 repr(C) 结构嵌入到常规结构中。

    假设我们有一个库,它公开了一个带有两个 8 位数字的 C 结构,以及获取和返回该结构的方法:

    typedef struct {
        char a;
        char b;
    } tuple_t;
    
    tuple_t tuple_increment(tuple_t position);
    

    在这种情况下,您肯定想模仿该结构并匹配 Rust 中的 C 表示:

    #[repr(C)]
    struct Tuple {
        a: libc::char,
        b: libc::char,
    }
    

    但是,如果库返回指向结构的指针,而您永远不需要插入它(结构是不透明的),那么您无需担心repr(C)

    void tuple_increment(tuple_t *position);
    

    然后你可以使用那个指针并实现 Drop:

    struct TuplePointer(*mut libc::c_void);
    
    impl Drop for TuplePointer {
        // Call the appropriate free function from the library
    }
    

    【讨论】:

    • 低级程序员,别担心:未来的 rust 会完全移除这个丢弃标志。
    • Tracking issue。最近取得了一些进展,比那里出现的要多。我希望它会在今年的某个时候。
    • 也许这个答案应该解释更多?使用 repr(C) 在 ffi 中传递结构,如果需要,对“常规 Rust”结构使用 Drop。如果两者都需要,请将 repr(C) 结构嵌入到常规 rust 结构中。
    • @bluss 介意给我上次的更新看看和一些反馈吗?
    猜你喜欢
    • 2022-01-13
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 2020-05-05
    • 1970-01-01
    相关资源
    最近更新 更多