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。

相关推荐
caimouse6 小时前
ReactOS 图形系统分析(47):GDI 批处理 — gdibatch.c
c语言·开发语言
qq21084629536 小时前
在python中什么是 self 和 cls?
开发语言·前端·python
杨充6 小时前
05.多用组合和少继承
开发语言·bash
今天AI了吗6 小时前
从聊天到委派:AI Agent 如何推进长期任务
数据库·人工智能·python·sql·rust
傻啦嘿哟6 小时前
王者荣耀爬虫:爬取全英雄皮肤数据,用Python做可视化分析
开发语言·爬虫·python
AI直播技术杂谈7 小时前
直播画面突然模糊了,排查了三个小时
开发语言·php
菜冻鱼7 小时前
Python-pytorch-数据加载
开发语言·人工智能·pytorch·python·深度学习·机器学习
heimeiyingwang7 小时前
【架构实战】可观测性三支柱实战:Metrics、Logging、Tracing 如何统一落地
开发语言·架构·php
caimouse7 小时前
ReactOS 图形系统分析(53):系统库存对象 — stockobj.c
c语言·开发语言·spring