Rust中的临时指针是否正常?

时间:2017-01-23 21:05:54

标签: rust

我有这样的功能:

extern {
    fn foo(layout: *const RawLayout) -> libc::uint8_t;
}

fn bar(layout: Layout) -> bool {
    unsafe {
        foo(&layout.into() as *const _) != 0
    }
}

其中Layout是可以转换的可复制类型.into()RawLayout

我想确保我了解正在发生的事情,因为它不安全。据我了解,layout.into()创建了一个临时RawLayout,然后&对其进行了引用,as *const _将其转换为原始指针(*const RawLayout) 。然后调用foo()函数并返回,最后删除临时RawLayout

这是对的吗?或者,为什么我不应该这样做有一些棘手的原因?

1 个答案:

答案 0 :(得分:4)

你是对的。在这种情况下,首先调用foo,然后删除RawLayout。这在The Rust Reference中有解释(请点击链接查看实践中如何解决的具体示例):

  

临时值的生命周期通常是最里面的封闭   声明

但是,我更愿意遵循Shepmaster的建议。明确地引入局部变量将有助于代码的读者集中于更重要的事情,例如确保不安全的代码是正确的(而不是必须弄清楚临时变量的确切语义)。

如何检查

您可以使用以下代码检查此行为:

struct Layout;
struct RawLayout;

impl Into<RawLayout> for Layout {
    fn into(self) -> RawLayout {
        RawLayout
    }
}

impl Drop for RawLayout {
    fn drop(&mut self) {
        println!("Dropping RawLayout");
    }
}

unsafe fn foo(layout: *const RawLayout) -> u8 {
    println!("foo called");
    1
}

fn bar(layout: Layout) -> bool {
    unsafe {
        foo(&layout.into() as *const _) != 0
    }
}

fn main() {
    bar(Layout);    
}

输出结果为:

foo called
Dropping RawLayout