为什么通过指向移动变量的指针写入在 Rust 中没有被确定为 UB?
Why writing through a pointer to a moved variable has not been decided as UB in Rust?
我正在调查阻止 Rust 编译器优化 . I found this comment rust-lang 中提醒我的问题的可能原因。
We must not optimize away storage of locals that are mutably borrowed, because as @matthewjasper notes in #61430, it isn't decided that the following is UB:
let mut x = String::new();
let p = &mut x as *mut String;
let y = x;
p.write(String::new());
我以为 x
的生命周期在移动到 y
时就结束了。 p
在 .write()
通过时悬空。但为什么这不被定为UB?
在同一个线程中,更进一步,cramertj 的 other comment 我认为可以稍微解释一下这个问题。其他评论中举例说明的代码是:
let mut x = String::new();
let addr_x: *const String = reference_to_pointer(&x);
drop(x);
ptr::write(addr_x as *mut String, String::new());
此代码段的基本思想是能够 drop
一个局部值到 运行 其析构函数并重用其内存分配来存储新值。这是一个模式,有些人认为它可能有用,但其他人认为它应该是UB。
请记住,drop()
无论如何都不是一个特殊函数,它只是将 x
移动到它自己的范围内并立即完成,因此它或多或少等同于您的原始代码。您甚至可以使用 forget()
或将值推送到容器中,示例仍然有效。
请注意,如果您使用分配的动态内存(这就是 Vec
在幕后所做的),这个习惯用法实际上是有效的。这里的问题是它是否对堆栈分配的自动内存也有效。
我正在调查阻止 Rust 编译器优化
We must not optimize away storage of locals that are mutably borrowed, because as @matthewjasper notes in #61430, it isn't decided that the following is UB:
let mut x = String::new(); let p = &mut x as *mut String; let y = x; p.write(String::new());
我以为 x
的生命周期在移动到 y
时就结束了。 p
在 .write()
通过时悬空。但为什么这不被定为UB?
在同一个线程中,更进一步,cramertj 的 other comment 我认为可以稍微解释一下这个问题。其他评论中举例说明的代码是:
let mut x = String::new();
let addr_x: *const String = reference_to_pointer(&x);
drop(x);
ptr::write(addr_x as *mut String, String::new());
此代码段的基本思想是能够 drop
一个局部值到 运行 其析构函数并重用其内存分配来存储新值。这是一个模式,有些人认为它可能有用,但其他人认为它应该是UB。
请记住,drop()
无论如何都不是一个特殊函数,它只是将 x
移动到它自己的范围内并立即完成,因此它或多或少等同于您的原始代码。您甚至可以使用 forget()
或将值推送到容器中,示例仍然有效。
请注意,如果您使用分配的动态内存(这就是 Vec
在幕后所做的),这个习惯用法实际上是有效的。这里的问题是它是否对堆栈分配的自动内存也有效。