Rust 与动态大小的瘦指针

主要观点:Rust 与 C 的显著区别在于要求所有值都有定义的大小,这使得运行时边界检查和高级静态分析工具成为可能。对于动态大小类型(DST),Rust 使用厚指针实现该要求,每个指向动态大小值的指针是一个(地址,大小)元组。厚指针使用方便但有性能缺陷,会占用两倍寄存器空间。此页面是RFC 3536的补充,提议 Rust 应支持指向 DST 的薄指针。

关键信息

  • C 中的动态大小类型

    • 数组和字符串:C 中最简单的 DST 是动态分配的数组,其大小需作为参数传递。NUL 终止的字符串大小虽可计算但不固定,易导致字符串操作代码难以理解,现代系统编程语言避免使用。GLib 有类似的厚指针 idiom 用于动态大小值。
    • 灵活数组成员:在处理低级协议时常用,通过在结构末尾放置占位数组实现,C99 将其纳入语言。Linux 内核已逐渐采用 C99 灵活数组成员。
    • 指向不完整类型的指针:C 允许声明未定义的结构,形成不完整类型的指针,其指针可不指向实际对象,C 程序员常将其用于隐藏实现细节。
  • Rust 中的动态大小类型

    • 切片和字符串:Rust 有slicestr类型,指针是(地址,大小)元组,避免丢失值的大小信息。Rust 中对 C 灵活数组成员的等价实现也包含指针的大小信息。
    • 外部类型:Rust 程序员在编写 C API 的绑定时遇到问题,RFC 1861 提议引入外部类型,但存在语义冲突,有三种解决方案,需将不完整类型与灵活数组成员解耦。
  • !Sized 薄指针提案:基本目标是性能优化,将动态大小值视为有很多数组成员的联合,通过#[repr(thin_unsized)]属性标记 DST 类型为薄指针类型,并实现 ThinUnsized 特质来报告大小。薄指针 DST 在结构的最后字段时行为类似,且与 Mutex 和 Box 交互时,其报告的大小在对象的整个生命周期中不能改变。

重要细节

  • C 中许多现存库假设 size_t 和 uintptr_t 等价,代码中常使用指针大小的无符号整数。
  • Rust 中通过core::mem模块在运行时检查值的大小和对齐。
  • Rust 编译器已在自身代码中使用 extern 类型实现灵活数组成员。
  • 薄指针提案中对 Packet 类型的处理及相关安全特性等。
阅读 9
0 条评论