Zig 为 ArrayList 引入指针稳定性锁
Zig: Pointer Stability for ArrayLists
Zig 语言在 2026 年 8 月的更新中,将此前用于 Hash Map 的指针稳定性锁机制扩展到了 std.ArrayList。这意味着开发者现在可以通过调用 lockPointers() 和 unlockPointers() 来防止因列表扩容导致的指针失效问题。文章通过一个具体的内存安全漏洞案例,展示了未锁定指针时可能引发的段错误,以及启用该机制后如何快速定位问题。此外,更新还涉及将包管理功能从编译器迁移至构建系统,以及 SPIR-V 后端和 LLVM 后端的显著改进,进一步提升了 Zig 在图形编程和系统构建方面的能力。
我们既可以拥有 AOT 的蛋糕,也能吃到 JIT 的甜点!
HN 评论区
65- amluto
这看起来有点弱。
在像 Rust 这样的语言中,编译器会替你“锁定”指针,你根本不会忘记。
而在像 C++(大概也包括 Zig)这样的语言中,理论上可以让那些引用动态数组存储的迭代器和切片持有某种锁来固定存储位置。
但这个 API 要求程序员记得去锁定指针,还要求程序员在正确的代码区域内保持锁的存活。在我看来,甚至博客文章里的示例都把锁的获取完全放在了需要稳定性的函数之外,所以根本没有任何机制能正确管理锁的作用域。类型系统也帮不上忙——那个有问题的 parse 函数无法声明它需要一个指针锁定的 ArrayList 参数。
- _bohm
这是个不错的功能,但我总觉得,如果你需要集合中某个元素的稳定指针,那 ArrayList 可能就是选错的数据结构了?也许有人能出来举个例子,说明什么时候会这么做,而不是比如直接存一个索引。或者,你可以用 Unrolled Linked List(在 Zig 0.16 版本移除之前叫 SegmentedList,不知道为啥被移除了)。
- portly
如果你考虑到这与语言的其他部分是一致的,那么这就非常有道理了。这只是另一种在代码中设置“绊索”来捕获你自己编程错误的方式。类似于在函数中使用 assert 来验证输入和输出。
我经常使用 ArrayList,所以很兴奋能在代码中广泛添加这个功能来加固它们。
我能想象这并非人人都喜欢,但那样的话,你可能也不会喜欢其他任何显式特性。
- Rendello
顺便一提:Zig 的一个(语法)特性是我在 Rust 里非常怀念的,就在第二个代码块里展示了,即带前缀的多行字符串字面量,写法如下:
const text =
\\This is a long comment
\\But I can split it among lines arbitrarily
\\And keep my indentation.
;
我已经开始使用 Rust 宏库 `docstr` [1],它也能做到同样的事情:
const TEXT: &'static str = docstr!(
/// Now I can do it in Rust, too.
/// I prefer this style a lot of the time
/// for long texts.
);
它甚至支持宏(来自文档的示例):
let greeting: String = docstr!(format!
/// Hello, my name is {name}.
/// I am {} years old!
age
);
- boricj
我花了一分钟才理解,这是在断言容器内部的指针是否发生了变化,而不是像锁定 SDL 表面那样锁定/解锁数据结构。
我最近为 C++ 实现了一个自定义容器,用于存储路径,其组件可以被迭代,底层由 std::string 支撑。我只是存储索引和一个对字符串的引用,这样即使 std::string 在修改后发生重新分配,我的迭代器也不会失效。这比增加一点成本要安全得多,出错概率低得多。