Valgrind检测到无效的读取错误我不知道如何修复或更准确:我不知道问题是什么。
Invalid read of size 8
at 0x443212: std::vector<Tile*, std::allocator<Tile*> >::end() const
by 0x44296C: Collection<Tile*>::Iterator::operator++()
Iterator类非常简单(实际上是一个有点糟糕的编程),但现在足以满足我的需求。我认为有三种方法可以帮助我找到解决问题的方法:
Iterator(size_t x, size_t y, const TileCollection& tiles)
: mTiles(&tiles)
, mX(mTiles->begin())
, mY(mTiles->at(x).begin())
{
std::advance(mX, x);
std::advance(mY, y);
bool foundFirst = false;
while (!foundFirst)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundFirst = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
}
Iterator Iterator::operator++()
{
bool foundNext = false;
++mY;
while (!foundNext)
{
while (mY != mX->end() && *mY == 0) ++mY;
if (mY != mX->end()) foundNext = true;
else
{
++mX;
if (mX != mTiles->end()) mY = mX->begin();
}
}
return *this;
}
void TileCollection::add(Tile* tile)
{
Point2D p(tile->getPosition());
std::vector<Tile*> tmp(1, (Tile*)0);
if ((size_t)p.x >= mTiles.size())
mTiles.resize(p.x + 1, tmp);
if ((size_t)p.y >= mTiles.at(p.x).size())
mTiles.at(p.x).resize(p.y + 1, (Tile*)0);
mTiles.at(p.x).at(p.y) = tile;
++mNumTiles;
}
导致valgrind错误的实际代码是行:
while (mY != mX->end() && *mY == 0) ++mY;
... Iterator :: operator ++方法。
答案 0 :(得分:1)
在我看来,至少是operator++
if (mX != mTiles->end()) mY = mX->begin();
缺少合适的else子句。
考虑当mX
实际到达mTiles->end()
时会发生什么:您将输入外部while循环的新迭代;该循环中的第一行(导致Valgrind错误的行)将评估mX->end()
,从而尝试取消引用mX
- 但mX
为mTiles->end()
,而不是Iterator
更正取消引用集合的结束迭代器,因为它实际上不引用集合的元素。它看起来好像这可能是你的Valgrind错误的原因。
(请注意,构造函数基本上包含相同的代码。)
更一般地说,我认为您需要考虑如何处理到达二维数组的末尾。 operator++
的客户端如何检查它是否已到达迭代结束?当你的{{1}}到达二维数组的末尾时,你如何期待它?它应该保护自己不要经常被叫吗?
答案 1 :(得分:0)
您可以尝试拆分语句,以便找出错误发生的位置:
while (mY != mX->end()) // maybe here
{
if (*mY != 0) // maybe here
{
break;
}
++mY; // maybe here
}
使用GCC编译器选项-fno-inline
进行编译有助于获得更好的堆栈跟踪,这可以帮助您跟踪错误。它也会使你的程序变得非常慢,所以不要忘记以后删除它。