&mut T
和&mut T
导致编译错误;这很好,从客观上讲,可变地借两次是错误的.
*mut T
和*mut T
是未定义的行为,还是这是一种完全有效的行为?也就是说,可变指针别名有效吗?
更糟糕的是,&mut T
和*mut T
实际上按照预期编译和工作,我可以通过引用、指针修改一个值,然后再通过引用修改一个值...但我看到有人说这是未定义的行为.是的,"有人这么说"是我唯一的信息.
以下是我测试的内容:
fn main() {
let mut value: u8 = 42;
let r: &mut u8 = &mut value;
let p: *mut u8 = r as *mut _;
*r += 1;
unsafe { *p += 1; }
*r -= 1;
unsafe { *p -= 1; }
println!("{}", value);
}
当然,主要的问题是:
Note年的今天,感谢trentcl的pointing out this example actually causes a copy when creating p2
美元.这可以通过将u8
更换为非Copy
型来确认.然后,编译器抱怨移动.可悲的是,这并没有让我更接近答案,只是提醒我,我可以获得非预期的行为,而不是未定义的行为,仅仅是因为Rust的移动语义.
fn main() {
let mut value: u8 = 42;
let p1: *mut u8 = &mut value as *mut _;
// this part was edited, left in so it's easy to spot
// it's not important how I got this value, what's important is that it points to same variable and allows mutating it
// I did it this way, hoping that trying to access real value then grab new pointer again, would break something, if it was UB to do this
//let p2: *mut u8 = &mut unsafe { *p1 } as *mut _;
let p2: *mut u8 = p1;
unsafe {
*p1 += 1;
*p2 += 1;
*p1 -= 1;
*p2 -= 1;
}
println!("{}", value);
}
两者都产生:
42
这是否意味着指向同一位置的两个可变指针在不同时间被解引用不是未定义的行为?
我不认为在编译器上测试这一点是一个好主意,因为未定义的行为可能会发生任何事情,甚至打印42
就好像什么都没有错.无论如何,我都会提到它,因为这是我try 过的事情之一,希望得到一个客观的答案.
我不知道如何编写一个测试,该测试可能会强制执行不稳定的行为,这会让人非常明显,这不起作用,因为它没有按预期使用,如果这是可能的话.
我知道这很可能是未定义的行为,在多线程环境中无论发生什么都会中断.不过,我希望得到比这更详细的答案,尤其是如果可变指针别名不是未定义的行为.(事实上,这将是非常棒的,因为尽管我和其他人一样使用 rust 迹——至少可以说是内存安全性方面的原因……但我仍然希望保留一把猎枪,可以指向任何地方,而不用把它锁在我的脚上.我可以在C中使用别名"可变指针",而不用把脚炸掉.)
这是关于我是否can岁的问题,而不是关于我是否should岁.我想直面不安全的 rust 迹,只是为了了解它,但感觉没有足够的信息,不像C这样的"可怕"语言,关于什么是未定义的行为,什么不是.