RUST网络客户端的基本技术说明-裸指针和unsafe

一、unsafe

unsafe这个英文单词,几乎可以让人明白这种用法是为了兼容其它“低级”语言的用法的,意味着这种作法是不推荐不安全的。这种作法在c#等其它语言都有类似的形制。比如c#在操作指针时,也会有类似的操作。这也是后发的高级语言的一个痛点,如果想在某个领域尽快的扩大影响,就不可避免的已经在这个领域已经占据有广泛的影响力的语言。
从某种意义上来讲,在C/C++语言中直接操作汇编语言,也可以划到这种unsafe的用法中。
换句话说,新的高级语言提供了一系列的高级的安全用法,但是在某些情况下又必须使用一些其它不安全的用法打破自己的设计,为了安全计,就必须显示的标明这些操作行为是不安全的。一方面,可以提醒尽量不要使用这种操作;另一方面,也不断演进语言本身,把这种不安全的用法不断的降低范围。
在Rust中,也不可避免的出现这种现象。Rust之所以安全,就是因为其从设计上保证上内存应用的安全。但是正如前面所提到的,Rust不光要提供自己的安全用法,对已经存在的在Rust眼中不安全的用法,也不得不提供支持;另外,它自己本身也在一些特定的领域内提供了一些非安全的用法。
这里需要说的是,unsafe和safe和应用程序开发的BUG不能混淆在一起,符合安全规范的代码,未必不会有Bug,反之,也不代表一定会有bug。
在Rust中unsafe主要有几种用法 :
1、裸指针
2、可变静态变量
3、不安全函数
看一下相关的例程:

//裸指针
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
//可变静态变量
static mut N: i32 = 5;
unsafe {
    N += 1;
    println!("N: {}", N);
}
//不安全函数
unsafe fn foo() {
    //实现
}
fn main() {
    unsafe {
        foo();
    }
}

代码出自《RustPrimer》。

二、裸指针

在Rust中,为了保证内存的安全,在编译器级别进行了内存安全的类型检查和校验。但特定场合下,仍然需要对指针进行直接操作,形如const T和mut T在Rust中即是现在提到的“裸指针”。既然是裸指针,搞c++的就明白了,这玩意儿说白了整个一个不靠谱啊,主要表现为:
1、指针指向的内存是不可信的。
2、指针需要手动处理内存资源
3、Rust的所有权移动和生命周期无法在这方面应用。所以很容易出现悬垂指针。
4、没有别名或可变性的保障(不允许强转)
而在实际的应用中,裸指针和unsafe在Rust中的操作一般是引用和裸指针之间可以隐式转换,但隐式转换后再解引用需要使用unsafe。
看一下相关的例程:

// 显式
let a = 1;
let b: *const i32 = &a as *const i32; //或者let b = &a as *const i32;
// 隐式
let c: *const i32 = &a;
unsafe {
    println!("{}", *c);
}

代码出自《RustPrimer》。
代码很简单,没有什么可讲的,大家可以在机器上实践一下。

三、总结

完全打破对过去的依赖和支持,正如打破一个旧的秩序,就必须要建立一个新的秩序。但新旧秩序的交替之间的苦痛,又是不得不承受的一种莫名的心酸。Rust现在也在经历这种苦痛,能不能破茧而出,就看时间的造化了。
努力吧,归来的少年!
在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 是的,在 Rust 中使用指针(也称为“原生指针”)读取 ZST 类型的数据,基本只需要保证指针非空并且对齐即可。你可以使用 `std::ptr` 库中的函数来读取指针,比如 `read_volatile` 和 `write_volatile`。 在使用指针时,你需要注意 Rust 的内存安全机制。指针可能会绕过 Rust 的检查,因此你需要自己确保指针指向的内存区域是安全的。 此外,你还需要注意编译器优化。指针可能会被编译器优化掉,因此你需要使用 `#[inline(never)]` 来禁止编译器优化。 ### 回答2: 是的,当使用Rust语言读取零尺寸类型(ZST)的指针时,主要要求指针非空和对齐。零尺寸类型是指在内存中不占用空间的类型。 首先,指针非空意味着指针不为null。在Rust中,直接使用指针需要使用unsafe关键字,表明这段代码可能有潜在的不安全性。由于零尺寸类型没有实际占用内存,所以指针必须指向有效的内存地址,而不是空指针。 其次,对齐是指数据在内存中存放的边界对齐要求。在Rust中,每个类型都有固定的对齐要求,用于保证数据在内存中的正确读取和写入。对于读取ZST的指针,仍然需要保证指针所指向的内存地址满足对齐要求。 然而,需要注意的是,Rust语言对于使用指针存在严格的安全性限制。Rust的借用检查器无法对指针进行静态检查,指针的使用容易引发各种安全性问题,如悬垂指针、野指针等。因此,在使用指针时,必须小心谨慎,遵循Rust的安全用法,并通过unsafe块明确标记不安全的代码段。 综上所述,当使用Rust读取零尺寸类型的指针时,需要确保指针非空且对齐。尽管Rust提供了指针的功能,但其使用需要极高的谨慎性,并且需要明确标记为不安全的代码块。 ### 回答3: 是的,当使用Rust读取零大小类型(ZST)的指针时,我们基本上只需要确保指针非空和对齐。 首先,确保指针非空是很重要的,因为空指针是不安全的操作。在Rust中,当我们使用指针时,我们需要使用`*mut T`来声明一个可变的指针,或者使用`*const T`来声明一个不可变的指针。无论是哪种情况,我们都需要保证指针指向有效的内存地址,以避免引发未定义行为。 其次,对齐是另一个重要的方面。对齐要求确保我们读取或写入数据时,按照特定的方式对齐它们,以保证数据安全地存储在内存中。对于ZST来说,它们本身没有任何内容,因此对齐变得尤为重要,以确保其他数据的对齐方式不会受到影响。 Rust编译器默认会对齐数据,以提高性能并保证内存安全。在使用指针读取ZST时,这个对齐要求仍然存在。因此,如果我们使用指针访问ZST,请确保我们遵循Rust关于对齐的规则,以免导致未定义行为。 综上所述,当使用Rust读取ZST的指针时,我们只需满足指针非空和对齐的要求,以避免潜在的错误或不安全操作。然而,为了代码的可读性和可维护性,建议在使用指针时尽量遵循更严格的内存安全规范,如避免使用指针,而是使用Rust的安全指针类型。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值