Result<Vec<f64>, _> 中指向向量第一个元素的指针已损坏

Sak*_*oka 3 pointers ownership rust

我有一个Result<Vec<f64>, _>。当我尝试提取指向实际数组的指针时f64,我观察到该数组dptr指向的是预期数组的损坏版本(前 10 个字节已更改)。

为什么会发生这种情况,我该如何避免这种情况?

use std::error::Error;

fn main() {
    let res: Result<Vec<f64>, Box<dyn Error>> = Ok(vec![1., 2., 3., 4.]);
    let dptr: *const f64 = match res {
        Ok(v) => &v[0], 
        Err(_) => std::ptr::null(),
    };
    assert_eq!(unsafe { *dptr }, 1.0);
}
Run Code Online (Sandbox Code Playgroud)

结果:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `0.0`,
 right: `1.0`', src/main.rs:9:5
Run Code Online (Sandbox Code Playgroud)

操场

loo*_*ops 7

该程序的行为是未定义的,可以通过在 Miri 下运行它来看到这一点,Miri 是一个 Rust 解释器,有时可以检测到未定义的行为。(您可以在 Playground 中单击“工具”(右上角)->“Miri”来执行此操作):

error: Undefined Behavior: pointer to alloc1039 was dereferenced after this allocation got freed
 --> src/main.rs:9:25
  |
9 |     assert_eq!(unsafe { *dptr }, 1.0);
  |                         ^^^^^ pointer to alloc1039 was dereferenced after this allocation got freed
  |
  = 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
Run Code Online (Sandbox Code Playgroud)

这里发生的是释放后使用:该Ok(v) => &v[0],行将数据从v( 并因此res) 移动,导致它被释放。后来,用于其他变量的数据覆盖了现有数据(因为在释放其指向的内存后使用指针是未定义行为)。

res如果您尝试在不使用 的情况下以正常方式读取数据unsafe,则会出现针对此问题的编译时错误:

error[E0382]: use of partially moved value: `res`
 --> src/main.rs:9:10
  |
6 |         Ok(v) => &v[0],
  |            - value partially moved here
...
9 |     dbg!(res.unwrap()[0]);
  |          ^^^ value used here after partial move
  |
  = note: partial move occurs because value has type `Vec<f64>`, which does not implement the `Copy` trait
help: borrow this field in the pattern to avoid moving `res.0`
  |
6 |         Ok(ref v) => &v[0],
  |            +++
Run Code Online (Sandbox Code Playgroud)

(操场)