#include <vector>
struct Node;
std::vector<Node> heap;
struct Node {
int x, c;
explicit Node(int x): x(x), c(0) {}
void update() {
if(x > 0) {
if(c == 0) {
c = heap.size();
heap.emplace_back(x / 2);
}
heap[c].update();
}
}
};
int main() {
heap.emplace_back(100);
heap.back().update();
}
考虑上面的代码。g++ -fsanitize=address
当用( )编译gcc version 10.2.0 (Ubuntu 10.2.0-5ubuntu1~20.04)
然后运行时,我得到AddressSanitizer: heap-use-after-free
. 经过一番谷歌搜索后,当我尝试访问先前已释放的指针时,似乎会发生此错误。检查 ASan 的输出表明该对象已被 vector.emplace_back 释放。我相信这是矢量调整自身大小的结果,并得到了heap.reserve(1000)
使代码运行良好的事实的支持。
然后我尝试用 push_back 替换 emplace_back,产生了类似的结果。但是,用循环替换递归可以正常工作。
int main() {
heap.emplace_back(100);
int prevc = 0;
while(true) {
int x = heap[prevc].x, c = 0;
if(x > 0) {
if(c == 0) {
c = heap.size();
heap.emplace_back(x / 2);
}
prevc = c;
}else {
break;
}
}
}
经过进一步检查,似乎在第一次调用update()
. 此外,访问heap[0]
andheap[1]
很好,但访问heap[c]
失败。
现在我很困惑。我找不到任何未定义的行为,也看不到向量内部调整大小导致我无法访问元素的任何原因。此外,我不确定为什么这仅会因递归而失败。我究竟做错了什么?