我有这样的功能:
extern {
fn foo(layout: *const RawLayout) -> libc::uint8_t;
}
fn bar(layout: Layout) -> bool {
unsafe {
foo(&layout.into() as *const _) != 0
}
}
Run Code Online (Sandbox Code Playgroud)
Layout
可转换.into()
的可复制类型在哪里RawLayout
?
我想确保我理解发生的事情,因为它不安全.据我所知,layout.into()
创建一个临时的RawLayout
,然后&
对它进行引用,as *const _
并将其转换为原始指针(*const RawLayout
).然后foo()
调用该函数并返回,最后RawLayout
删除临时函数.
那是对的吗?还是有一些棘手的原因我不应该这样做?
你是对的。在这种情况下,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);
}
Run Code Online (Sandbox Code Playgroud)
输出是:
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);
}
Run Code Online (Sandbox Code Playgroud)