问题
最近做图论题发现一个bug, 在这里记录一下:
vector<pair<int, int>> vp{ {1, 2}, {2, 3} };
for (size_t i{}; i < 4; ++i) {
if (i < vp.size()) {
auto& [a, b] = vp[i];
vp.emplace_back(a, b);
cout << a << " : " << b << endl;
}
}
在 address-sanitizer 直接报:
==1705==ERROR: AddressSanitizer: heap-use-after-free on address 0x0001051006f0 at pc 0x000102669330 bp 0x00016d796790 sp 0x00016d796788
问题出在哪了呢?
定位一下错误发现, 原来是引用搞的鬼, 再来看下面的精简一点的例子, 就能发现问题了:
vector<int> vp{1, 2, 3};
for (size_t i{}; i < 4; ++i) {
if (i < vp.size()) {
int& a = vp[i];
cout << "before: " << a << endl; // 1
vp.push_back(a);
cout << "after: " << a << endl; // X: 不能访问 a 了
}
}
在 before 输出 1 之后, 出现内存问题, 也就是说问题出现在 push_back 这里了, 构造本身是没问题的, 但是 &
这个符号是不对的(又一次被&
坑了), 容器内元素的引用传入容器就会导致引用变量变成野指针!
这时候注释掉第七行, 问题就解决了, 但这也说明引用变量的一个问题, 引用的变量 通过 push_back 传入容器之后, 本身的值就会失效, 当然这只是针对容器内元素的引用来说的, 如果传入的是外部变量的引用, 则没有这个问题.