内容提要
Rust 1.99.0 稳定了用 Rust 定义 C-ABI 可变参数函数(支持 "C" 和 "C-unwind"),并支持非 "C" ABI 的裸可变参数函数;同时稳定了获取裸指针大小和对齐的三个函数,并更新 Box::leak 文档,建议改用 Box::into_non_null。
延伸解读
C-ABI 可变参数函数:从调用到定义
此前 Rust 只能调用外部定义的 C 可变参数函数(如 libc::printf),1.99.0 起可直接用 Rust 定义 "C" 和 "C-unwind" ABI 的可变参数函数。参数列表类型为 VaList,与 C 的 va_list 跨目标 ABI 兼容;可读取的类型受 VaArgSafe 约束。这为需要导出 C 风格可变参数接口的库提供了原生实现路径,但读取参数仍需 unsafe,调用方必须保证参数类型与数量符合约定。
裸指针大小与对齐:三个函数稳定
本次稳定了 Layout::for_value_raw、mem::size_of_val_raw 和 mem::align_of_val_raw,用于获取裸指针所指向值的大小与对齐。对 Sized 类型,该操作本身是安全的;对非 Sized 类型,则需满足相应的安全要求。这填补了通过裸指针处理动态大小类型时的元数据查询能力,但使用者仍需自行确保指针有效且指向合法对象,否则可能触发未定义行为。
Box::leak 文档转向 into_non_null
Rust 1.99.0 未改变语言语义,但更新了 Box::leak 的文档,建议避免“泄漏后再释放该内存”的模式。原因在于这类代码与当前及未来可能的编译器优化存在不良交互,在自定义分配器即将稳定之际尤其成问题。文档推荐改用 Box::into_non_null,且该建议同样适用于标准库中其他 leak 函数。已有相关代码的开发者应关注这一方向性调整。
Q&A
Rust 1.99.0 如何更新?
如果你已经通过 rustup 安装了 Rust,可以运行 `rustup update stable` 来获取 1.99.0。
Rust 1.99.0 在可变参数函数方面有哪些新特性?
Rust 1.99.0 稳定了使用 "C" 和 "C-unwind" ABI 定义 C-ABI 可变参数函数,也稳定了支持非 "C" ABI 的裸可变参数函数(需通过内联汇编编写)。
如何在 Rust 中定义 C-ABI 可变参数函数?
使用 `unsafe extern "C" fn` 并声明可变参数 `...`,例如 `unsafe extern "C" fn sum(mut args: ...) -> i32`,然后通过 `args.next_arg::<i32>()` 读取参数。
VaList 类型是什么?
`...` 的类型是 `VaList`,它在各目标平台上与 C 的 `va_list` 类型 ABI 兼容。
Rust 1.99.0 稳定了哪些与裸指针大小和对齐相关的函数?
稳定了三个函数:`Layout::for_value_raw`、`mem::size_of_val_raw` 和 `mem::align_of_val_raw`。
为什么 Box::leak 的文档被更新?
因为发现某些使用 Box::leak 后释放内存的模式与当前及未来可能的编译器优化存在不良交互,尤其是在即将稳定自定义分配器时问题更严重,因此文档建议改用 Box::into_non_null。