相关疑难解决方法(0)

解除引用原始指针的语义是什么?

对于共享引用和可变引用,语义是明确的:只要您具有对值的共享引用,其他任何内容都不能具有可变访问权限,并且不能共享可变引用.

所以这段代码:

#[no_mangle]
pub extern fn run_ref(a: &i32, b: &mut i32) -> (i32, i32) {
    let x = *a;
    *b = 1;
    let y = *a;
    (x, y)
}
Run Code Online (Sandbox Code Playgroud)

编译(在x86_64上):

run_ref:
    movl    (%rdi), %ecx
    movl    $1, (%rsi)
    movq    %rcx, %rax
    shlq    $32, %rax
    orq     %rcx, %rax
    retq
Run Code Online (Sandbox Code Playgroud)

请注意,内存a指向只读一次,因为编译器知道写入b必须没有修改内存 a.

原始指针更复杂.原始指针算术和强制转换是"安全的",但取消引用它们不是.

我们可以将原始指针转换回共享和可变引用,然后使用它们; 这肯定意味着通常的引用语义,编译器可以相应地进行优化.

但是如果我们直接使用原始指针,那么语义是什么?

#[no_mangle]
pub unsafe extern fn run_ptr_direct(a: *const i32, b: *mut f32) -> (i32, i32) {
    let x = *a;
    *b = 1.0; …
Run Code Online (Sandbox Code Playgroud)

rust

11
推荐指数
1
解决办法
979
查看次数

别名可变的原始指针(* mut T)是否会导致不确定的行为?

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

当然,主要的问题是:

注意 —感谢trentcl 指出此示例在创建时实际上会导致复制p2。可以通过用u8Copy类型替换来确认。然后,编译器抱怨此举。可悲的是,这并不能使我更接近答案,仅是提醒我,仅由于Rust的move语义,我就可以得到意想不到的行为而不会成为未定义的行为。

fn main() { …
Run Code Online (Sandbox Code Playgroud)

unsafe undefined-behavior rust

10
推荐指数
1
解决办法
158
查看次数

标签 统计

rust ×2

undefined-behavior ×1

unsafe ×1