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。

相关推荐
大圣编程31 分钟前
Java 多维数组详解
java·开发语言
殳翰3 小时前
下服务器端开发流程及相关工具介绍(C++)
开发语言·c++
落寞的星星4 小时前
这个对象就包含了已经转换好的DFA和各种词法分析器运转所需要的参数。下一步,我们就可以用ScannerInfo对象创建出Scanner对象,请看下面的代码:
开发语言·c#
nothing&nowhere4 小时前
用 Python 做问卷数据清洗:无效样本检测与处理实战
开发语言·python·数据清洗·数据处理·问卷星·问卷星脚本·刷问卷
2601_961593424 小时前
Rust 开发环境配置繁琐?RustRover 开箱即用搞定编码调试
开发语言·后端·macos·rust
HZZD_HZZD5 小时前
DL/T 645-2026新国标深度解读与智能电表协议适配实战:从帧结构变化到Java采集器升级的全链路改造方案
java·开发语言
冬奇Lab6 小时前
每日一个开源项目(第154篇):Warp - 从‘好看的终端‘到 Agentic 开发环境
人工智能·rust·llm
多加点辣也没关系7 小时前
JavaScript|第4章:类型转换
开发语言·javascript
聪慧的水蜜桃7 小时前
【YFIOs】用C#开发硬件之设备上云
开发语言·c#
yqcoder7 小时前
httpOnly 是什么,又有什么用?
开发语言·前端·javascript