Are raw pointers to temporaries ok in Rust?

2019-06-15 14:20发布

I have a function like this:

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

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

Where Layout is a copyable type that can be converted .into() a RawLayout.

I want to make sure I understand what is happening as it is unsafe. As I understand it, layout.into() creates a temporary RawLayout, then & takes a reference to it, and as *const _ converts it to a raw pointer (*const RawLayout). Then the foo() function is called and returns, and finally the temporary RawLayout is dropped.

Is that correct? Or is there some tricky reason why I shouldn't do this?

标签: rust
1条回答
趁早两清
2楼-- · 2019-06-15 15:02

You are right. In this case, foo is called first and RawLayout is dropped afterwards. This is explained in The Rust Reference (follow the link to see concrete examples of how this works out in practice):

The lifetime of temporary values is typically the innermost enclosing statement

However, I would rather follow Shepmaster's advice. Explicitly introducing a local variable would help the reader of the code concentrate in more important things, like ensuring that the unsafe code is correct (instead of having to figure out the exact semantics of temporary variables).

How to check this

You can use the code below to check this behavior:

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);    
}

The output is:

foo called
Dropping RawLayout
查看更多
登录 后发表回答