Jon*_*fer 4 undefined-behavior rust
Rust 参考和Rustonomicon都明确指出“生成”悬空引用是未定义的行为。
以这段代码片段为例:
fn main() {
let p: std::ptr::NonNull<u8> = std::ptr::NonNull::dangling();
#[allow(unused_variables)]
let r: &u8 = unsafe { std::mem::transmute::<_, _>(p) };
}
Run Code Online (Sandbox Code Playgroud)
在操场上通过 Miri 运行它会产生:
error: Undefined Behavior: constructing invalid value: encountered a dangling reference (address 0x1 is unallocated)
--> src/main.rs:4:27
|
4 | let r: &u8 = unsafe { std::mem::transmute::<_, _>(p) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered a dangling reference (address 0x1 is unallocated)
|
= help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
= help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
= note: BACKTRACE:
= note: inside `main` at src/main.rs:4:27
Run Code Online (Sandbox Code Playgroud)
当然,Rust 语言可以根据创建者的需要自由定义 UB 一样多的东西。我想知道的是这个未定义行为规则的优点是什么(通常,UB是在一种语言中引入的,以允许优化或简化事情)。
然而,根据上面链接的参考,未定义的行为可能已经通过编写一个本地的悬空引用而被触发,而我无法想出它的用途。
所以:
Cha*_*man 13
事实上,仅仅创建一个无效引用就是UB,这意味着无效引用不能存在。这对于诸如循环不变代码运动之类的优化很重要。
以下面的代码为例:
fn foo(arr: &[u32], cond: &bool) -> u32 {
let mut result = 0;
for &v in arr {
if *cond {
result += v;
}
}
result
}
Run Code Online (Sandbox Code Playgroud)
编译器可以通过将条件提升到开头来优化这一点,从而允许进一步优化,例如自动向量化:
fn foo(arr: &[u32], cond: &bool) -> u32 {
let mut result = 0;
if *cond {
for &v in arr {
result += v;
}
}
result
}
Run Code Online (Sandbox Code Playgroud)
但如果*cond可以悬空,则此优化无效:*cond例如可以触发段错误,并且如果数组为空,则原始版本不会发生这种情况。
参考文献必须始终有效。
与“引用可能有效也可能无效,但取消引用无效引用是未定义的行为”相比,这是一个更容易推理和使用的规则。允许这种行为也没有任何好处;如果您想引用一个可能有效或无效的值,则有原始指针或MaybeUninit用于此目的。
有一个原则是“安全的 Rust 不会导致未定义的行为”(或者反身的“如果一组参数可能导致未定义的行为,那么它必须被标记unsafe”)。希望你能理解为什么人们希望这是真的,并努力保证它。如果这样的原则不存在,那么这个函数就不能保证它不会导致未定义的行为:
fn get(ref: &u8) -> u8 {
*ref
}
Run Code Online (Sandbox Code Playgroud)
未定义的行为,并且unsafe有一套非常混乱的规则需要遵循,以确保你做对了。但规则和后果不应该泄漏到unsafeRust 中的非代码中。
在所有实践中,我无法想到简单地创建引用会导致理智的编译器引起问题的情况,因为如果创建了它但没有使用它,那么它就会被消除死代码(但话又说回来,编译器不理智)。因此,我认为该规则不是出于技术原因,而是出于务实的原因。
| 归档时间: |
|
| 查看次数: |
278 次 |
| 最近记录: |