使用Drop trait释放repr(C)结构的正确习惯用法

Del*_*ore 11 c memory rust

这段代码工作正常,但在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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

它链接到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     }
Run Code Online (Sandbox Code Playgroud)

正确的方法是什么,以确保DbaxCell正确清理这些s并且没有给出警告?

She*_*ter 9

我认为你正在混淆两个概念.一个结构应该是repr(C),如果你想为结构的布局直接对应到结构布局的C编译器会放下它.也就是说,它具有相同的记忆内repr表达.

但是,你不要需要,如果你只是抱着一个原始指针,而不是要通过保持机构回到C.在这种情况下"删除短期的解决方案repr(C)".

更多地解释错误......

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

这在24585号问题中讨论过.删除对象时,会设置隐藏标志("状态"),表示该对象已被删除,从而防止发生多次丢弃.但是,隐藏位意味着你在Rust中看到的内容与C中结构的字节不一致,否定了它的用途repr(C).

正如@bluss所说:

低级程序员,不要担心:未来Rust会完全删除这个drop标志.

用于repr(C)在FFI中传递结构,并Drop在需要时使用"常规Rust"结构.如果需要两者,请将repr(C)结构嵌入常规结构中.

想象一下,我们有一个库,它公开了一个带有两个8位数的C结构,以及获取并返回该结构的方法:

typedef struct {
    char a;
    char b;
} tuple_t;

tuple_t tuple_increment(tuple_t position);
Run Code Online (Sandbox Code Playgroud)

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

#[repr(C)]
struct Tuple {
    a: libc::char,
    b: libc::char,
}
Run Code Online (Sandbox Code Playgroud)

但是,如果库返回指向结构的指针,并且您永远不需要戳它(结构是不透明的),那么您不必担心repr(C):

void tuple_increment(tuple_t *position);
Run Code Online (Sandbox Code Playgroud)

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

struct TuplePointer(*mut libc::c_void);

impl Drop for TuplePointer {
    // Call the appropriate free function from the library
}
Run Code Online (Sandbox Code Playgroud)

  • 低级程序员,不要担心:未来的生锈将完全消除这种下降标志. (3认同)
  • 也许这个答案应该解释一下?使用`repr(C)`来传递ffi中的结构,如果需要,可以在"常规Rust"结构上使用`Drop`.如果你需要两者,在常规的rust结构中嵌入`repr(C)`结构. (3认同)