在将变量声明为引用时,堆在释放后使用
heap-use-after-free when declaring a variable as a reference
下面粘贴的代码返回一个heap-use-after-free
错误。当我删除引用符号'&'时在具有coord &c = q.front(); q.pop();
的线路上,错误被解决。
据我所知,当没有更多引用时,C++垃圾收集器会删除我从q.front((中检索到的coord。尽管这里似乎coord &c
中的C在从队列中弹出后立即从堆中删除,并且试图在下一行访问C会导致错误。
然而,这种情况并不是每次都会发生,所以我想知道为什么会发生这种情况。
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
if(grid.size() == 0) return 0;
typedef pair<int,int> coord;
queue<coord> q;
const int m = grid.size();
const int n = grid[0].size();
int i_in[] = {0,0,1,-1};
int j_in[] = {1,-1,0,0};
int ans = 0;
for(int i = 0; i < m; ++i)
{
for(int j = 0; j < n; ++j)
{
if(grid[i][j] == '1')
{
++ans;
q.push(coord(i,j));
while(q.size() > 0)
{
coord &c = q.front(); q.pop();
grid[c.first][c.second] = '*';
for(int k = 0; k < 4; ++k)
{
int newi = c.first + i_in[k];
int newj = c.second + j_in[k];
if(newi >= 0 && newi < m &&
newj >= 0 && newj < n &&
grid[newi][newj] == '1')
{
q.push(coord(newi, newj));
}
}
}
}
}
}
return ans;
}
};
coord &c = q.front();
^^^此行将c
设置为引用当前位于队列前面的pair<int,int>
。
q.pop();
^^^这一行删除队列前面的项目,在过程中销毁它(。因此,在这一行返回后,c
引用指向一个无效对象,这意味着尝试使用c
将调用未定义的行为。
然而,这种情况并不是每次都会发生,所以我想知道为什么会发生这种情况。
发生的是未定义的行为,当您尝试使用悬挂引用时会调用该行为。关于未定义行为的有趣之处在于;事情似乎进展顺利"是一个有效的结果,就像发生的任何其他事情一样——因为一旦你调用了未定义的行为,所有的赌注都会被取消,编译器编写者就没有任何义务让程序从此正确运行,世界就崩溃了。
要解决这个问题,您可以删除"与"符号(就像您所做的那样(,这样就没有引用,因此就不会出现悬空引用问题(因为您已经将队列的pair<int,int>
对象复制到了局部变量中(;或者,您可以将对q.pop()
的调用向下移动到while循环的末尾,这样它只会在您对c
引用的所有使用都已执行之后发生。
相关文章:
- 在将变量声明为引用时,堆在释放后使用
- 如果包含映射的静态库与可执行文件和动态库链接,静态映射(变量)是否会被多次释放?
- 在C++中创建和释放临时虚拟变量
- 如果一个变量在它之前释放了另一个(相同的数据类型)变量,如何将其分配给内存?
- 函数调用后释放变量
- 释放指向保留嵌套变量内存地址的结构的指针
- C++ 中指针变量的内存释放
- 如何释放为指针变量本身提供的内存?
- C 全局对象变量内存释放
- 如何释放C++异常类析构函数中的变量
- 如果我将内存动态分配给静态变量,我应该释放它还是会自动释放它
- 释放中间变量
- 如何释放局部变量拥有的资源
- 分配给 cpp 中定义的全局静态变量的内存是否在 C++ 中删除其类的实例后释放
- 为什么不能在堆栈上释放变量?
- 是否释放了局部变量的地址
- pthreads 中的条件变量并释放多个锁
- SysFreeString 不会释放变量
- 需要释放具有保留内存的 c++ Do 局部变量
- C++和Win32:我什么时候必须释放变量等