我在 godbolt 里复现这个问题:
https://godbolt.org/z/h45896sM5只会在 O1 优化下出现,是一个悬垂引用导致的巧合。
1. memo.GetReduceGroupId(group_id) 返回的临时的 std::optional<ReducedGroupId> 存储在 [rsp + 16] 到 [rsp + 24]。optional 本身共 9 个字节,前 8 个字节是 ReducedGroupId ,后跟一个 bool 。
2. reduced_group_id 为 .value() 返回的地址,即 rsp + 16 ,注意这是一个栈上的临时空间,reduced_group_id 为悬垂引用。后续用 rbx 存储 reduced_group_id 引用的地址。
3. tmp.push_back(4) 恰好将 4 ( 8 个字节)存储到 [rsp + 16],覆盖了 reduced_group_id 指向的内存。编译器认为这是安全的,因为临时的 std::optional<ReducedGroupId> 已经析构,这导致后续读取 reduced_group_id 的值为 4 。