当前位置: 首页 > 知识库问答 >
问题:

从语义的角度来看,一个未定义的行为发生的时刻是什么`

古起运
2023-03-14

正如参考文献所说

打破指针别名规则。

这真的很模糊
我想知道

是下面的任何一个,还是别的什么?

  1. 定义两个

例如,这段代码明显是UB:

unsafe {
    let mut x = 123usize;
    let a = (&mut x as *mut usize).as_mut().unwrap(); // created, but not accessed
    let b = (&mut x as *mut usize).as_mut().unwrap(); // created, accessed
    *b = 666;
    drop(a);
}

但如果我修改代码如下:

struct S<'a> {
    ref_x: &'a mut usize
}

fn main() {
    let mut x = 123;
    let s = S { ref_x: &mut x }; // like the `T` in `ManuallyDrop<T>`
    let taken = unsafe { std::ptr::read(&s as *const S) }; // like `ManuallyDrop<T>::take`
    // at thist ime, we have two `&mut x`
    *(taken.ref_x) = 666;
    drop(s);
    // UB or not?
}

第二个版本也是UB吗?
第二个版本与std::mem::ManuallyDrop完全相同。如果第二个版本是UB,是std::mem的安全漏洞::ManuallyDrop


共有1个答案

齐凯康
2023-03-14

实际上,存在多个

最简单的例子是:

fn main() {
   let mut i = 32;
   let j = &mut i;
   let k = &mut *j;

   *k = 3;

   println!("{}", i);
}

但是请注意,由于借用规则,您无法同时访问其他别名。

如果您查看ManuallyDrop的实现::采取

pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
    ptr::read(&slot.value)
}

您会注意到,没有可同时访问的

这真的很模糊。我想知道

运气不好,因为按照Nomicon的规定:

不幸的是,Rust并没有真正定义它的别名模型。

原因是语言团队希望确保他们达成的定义既安全(显然如此)、实用,又不会关闭可能的改进之门。这是一项艰巨的任务。

Rust Unsafe Code Guidelines工作组仍在努力确定确切的边界,尤其是拉尔夫·荣格(Ralf Jung)正在研究一种称为堆叠借用(Stacked Borrows)的别名操作模型。

注意:堆叠借用模型是在MIRI中实现的,因此您可以通过在MIRI中执行代码来根据堆叠借用模型验证您的代码。当然堆叠借用仍然是实验性的,所以这并不能保证任何事情。

我个人同意谨慎。由于没有具体说明确切的模型,规则一直在变化,因此我建议尽可能采取更严格的解释。

因此,我解释了

在代码的任何一点上,如果其中一个是

也就是说,我认为形成一个

这可能过于谨慎,但至少如果别名模型最终比计划的更保守,我的代码仍然有效。

 类似资料:
  • 问题内容: 我正在关注egghead.io上的视频教程,但是在尝试遵循他在创建工厂时的示例时,我一直收到“未定义角度”的参考错误,但是我包含了角度脚本 这是我的html页面: 这是我的JavaScript文件“ main.js”: 我已经读过几篇类似的文章,如果我写错了,请纠正我,但是我认为这与引导绑定有关,并且我尝试使用手动引导,但没有成功,仍然遇到相同的错误。 但是我想知道的是,为什么这可以在

  • 我试图设置一个setTimeout,在一个开关内,在一个foreach内,在一个函数内… TypeError: undefined不是对象(计算“this。数据’) 我试过了 他们都得到未定义的错误。

  • 尽管标题出现了,但这并不是一个哲学问题。 从未初始化的数组读取 使用错误数据 使用不可移植构造。(即内存分配的细节1) 导致具有的行为 标准没有要求产生可预测的效果 我会称之为“未定义的行为”。但也许我错过了什么(?) null null

  • 问题内容: 我试图了解如何开发独立的Javascript代码。我想用命令行运行测试和模块编写Javscript代码。所以,我已经安装,并伴随着图书馆,和。 我的目录结构如下所示: 我在用下面的代码编写的一个小模块在哪里: 并且是测试: 然后,我尝试从顶级目录运行(因此看到该目录): 所以我的问题是: 这是构造代码的正确方法吗? 为什么我的测试无法运行? 学习这种东西的最好方法是什么?我很难在Goo

  • 我有以下html: 我试图获得如下范围: 但我收到:。 我是angularJS初学者,我只是不明白为什么这不起作用。 更新:这也不起作用: 更新2:我试图在控制台中打印出作用域的所有代码: