3

由于我无法弄清楚的段错误,我在我的程序上运行了 valgrind。它在这里检测到一个问题...

Address 0x75c7670 is 0 bytes inside a block of size 12 free'd
  at 0x4024851: operator delete(void*) (vg_replace_malloc.c:387)
  by 0x805F6D8: std::list<Object*, std::allocator<Object*>::remove(O
  bject* const&) (new_allocator.h:95)

删除是在这种方法...

void ObjectManager::AdjustGridCoord( int x, int y, Object* const obj ) {
  // GetTileX and GetTileY guaranteed to be valid indices
  int newX = ObjectAttorney::GetTileX( obj );
  int newY = ObjectAttorney::GetTileY( obj );
  if ( x != newX || y != newY  ) {
    m_objGrid[x][y].remove( obj );
    m_objGrid[newX][newY].push_back( obj );
  }
} 

我不认为从列表中删除指针会调用delete它。这里有什么可疑之处?如果您需要更多信息,请告诉我。

PS 以前在调试时,我注意到问题的发生是因为 GetTileX 和 GetTileY不是有效的索引,并且会返回像 13775864 这样的荒谬数字。我认为这与delete问题有关,并且删除或 push_back 导致了问题。

编辑:这是另一个代码片段

for ( unsigned int x = 0; x < m_objGrid.size(); ++x ) {
  for ( unsigned int y = 0; y < m_objGrid[x].size(); ++y ) {
    for ( ListItr obj = m_objGrid[x][y].begin(); obj != m_objGrid[x][y].end(); ++obj ) {
      ObjectAttorney::UpdateAI( *obj );
      AdjustGridCoord( x, y, *obj );
    }
  }
}

AdjustGridCoord 会使迭代器无效吗?

4

2 回答 2

2

作为对您的编辑的回应,是的,我认为您已经正确诊断了它。

您的代码有点混乱(主要是因为您将名称obj同时指定给对象指针和引用列表中其单元格的迭代器),但是这一行:

m_objGrid[x][y].remove( obj );

删除obj对象的位置将使obj调用函数中的迭代器无效。从 valgrind 输出中可以看出,删除对象会导致列表删除包含对象指针的单元格,这就是obj迭代器所指的内容。因此,obj迭代器无效。然后,当调用返回时,接下来发生的事情就是循环增量:

++obj

在这里,obj是迭代器,它刚刚失效,并且它的引用单元格在对 的调用中被删除AdjustGridCoord。这会导致访问被释放的内存,这就是 valgrind 所抱怨的。

你基本上有两个选择:

  1. 重新构建循环,以便在调用之前获得后续迭代器AdjustGridCoord
  2. 遍历列表一次并记录您需要在其他数据结构中进行的更改,然后在该辅助“更改列表”结构上进行第二次循环,并在该循环中实际对原始列表进行这些更改。

2 的一个示例是创建一个std::vector<std::pair<unsigned int, unsigned int> >保存您需要调用的坐标的 a AdjustGridCoord,然后对其进行迭代以实际进行调用。

于 2010-07-30T00:21:20.620 回答
1

大小为 12 free'd 的块实际上是列表节点,而不是您的对象。所以,std::list::remove()没有调用delete你的指针,它只是deleted 包含它的列表节点。

我无法从您的代码片段中看出您实际(错误地)使用该内存的位置。

于 2010-07-29T23:07:52.307 回答