为什么通过指向移动变量的指针写入在 Rust 中没有被确定为 UB?

Zhi*_* Ma 5 undefined-behavior rust

我正在调查阻止 Rust 编译器优化某些代码片段的可能原因。我在 rust-lang 的一个 issue 中发现了这条评论,它提醒了我。

我们不能优化可变借用的局部变量的存储,因为正如@matthewjasper 在 #61430 中指出的那样,并没有决定以下是 UB:

let mut x = String::new();
let p = &mut x as *mut String;
let y = x;
p.write(String::new());
Run Code Online (Sandbox Code Playgroud)

我认为x当它移动到y. p.write()通过时晃来晃去。但为什么这不决定为UB?

rod*_*igo 4

在同一个线程中,更进一步,cramertj另一条评论我认为解释了这个问题。其他评论中示例的代码是:

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());
Run Code Online (Sandbox Code Playgroud)

此代码片段的基本思想是能够对drop本地值运行其析构函数并重用其内存分配来存储新值。这是一种模式,有些人认为它可能有用,但另一些人认为它应该是 UB。

请记住,这drop()无论如何都不是一个特殊函数,它只是将 移动x到其自己的作用域中并立即完成,因此它或多或少相当于您的原始代码。您甚至可以使用forget()该值或将其推送到容器中,并且该示例仍然有效。

请注意,如果您使用分配的动态内存,则此习惯用法实际上是有效的(这就是Vec幕后的操作)。这里的问题是它对于堆栈分配的自动内存是否也有效。