Rust 中 unsafe 关键字的语义

之前我都没注意到,不同的场景下 unsafe 关键字的语义可能有很大不同(可能随着我的理解深入,能把这些语义统一起来吧)。本文主要介绍在三个不同场景下 unsafe 的语义。

unsafe block

unsafe block 里的 unsafe 是强制性的,是用于"提权"的。rust 代码中有些操作不用 unsafe block 提权是不能通过编译的,比如:

  • deref raw ptr
  • 调 FFI
  • inline asm
  • 调 unsafe fn

所以这里的 unsafe 的语义是"提权",是编译器强制要求开发者添加的。

unsafe fn

这里的 unsafe 是规范性的,用于提醒函数的调用者,需要满足特定的条件才能调用此函数。

unsafe fn 里的 unsafe 并不能提权,也就是函数实现里如果想进行 unsafe 的操作,还需要再使用 unsafe block(可能旧版本的 rust 并不需要,这一点有待验证)。反过来,函数内使用 unsafe block,不代表函数一定是 unsafe fn 的。所以说这里的 unsafe 是规范性的,是开发者为了保证代码质量自觉标明的。

unsafe trait

这里的 unsafe 也是规范性的,用于提醒 trait 的实现者,在编写 impl trait 时要注意满足特定的语义。以典型的 unsafe trait Sync 为例,开发者都相信,实现了 Sync 的类型,其引用可以在线程间传递。如果有人在实现 Sync 时,没有保证目标类型的引用可以在线程间传递,就可能让人们在使用这个类型时发生 UB。

比较微妙的一点是,其实所有 trait 都要求实现者在实现时合理地实现每个接口,那 unsafe trait 有什么特殊之处呢?关键在于,unsafe trait 实现的语义要被 unsafe code 依赖,并且会影响 unsafe code 是否会发生 UB。

一般的 trait 所承载的语义,并不会影响使用这个 trait 的代码。比如,如果一个 trait 只被 safe code 调用,无论其内部实现为何,其绑定的语义为何,safe code 都不会发生 UB,因为 safe code 能做的事情有限,他调用一个胡乱实现的 trait,可能会出 bug,但不会出 UB。即使是 trait 的实现内部会发生 UB,也不会传递到 safe code 中,所以不算 safe code 发生 UB。

但如果一个 trait 会被 unsafe code 调用,并且 unsafe code 会基于这个 trait 的语义做一些事,那就可能因为 trait 的实现没有满足语义要求,而导致 unsafe code 中发生 UB。对于这种 trait,就应该规范地将其标为 unsafe trait。

相关推荐
AI砖家1 小时前
前端 JavaScript 异步处理全方案详解:从回调到 Observable
开发语言·前端·javascript
思麟呀1 小时前
C++工业级日志项目(七)日志器核心
linux·开发语言·c++·windows
2401_873479401 小时前
如何用IP离线库批量清洗订单IP,自动标注省市区?
开发语言·网络·python
lcj25112 小时前
vector的基本使用 + 手搓成员变量 size capacity begin end operator[] reserve扩容 拷贝构造 赋值析构
开发语言·c++·笔记·面试
GHL2842710902 小时前
Qt Creator 19.0.0 (Community)下载
开发语言·qt
之歆2 小时前
Day21_电商详情页核心技术实战:从LESS预处理到复杂交互实现
开发语言·前端·javascript·css·交互·less
Mininglamp_27182 小时前
现在入局Agent开发还来得及吗?
java·开发语言
方也_arkling2 小时前
【Java-Day10】多态
java·开发语言