std :: list删除指针上的调用删除?

时间:2010-07-29 23:02:52

标签: c++ segmentation-fault valgrind delete-operator stdlist

我在程序上运行了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。这看起来有什么疑问?如果您需要更多信息,请告诉我们。

P.S。以前在调试时,我注意到发生了问题,因为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可以使迭代器无效吗?

2 个答案:

答案 0 :(得分:2)

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

您的代码有点令人困惑(主要是因为您将名称obj赋予对象指针和引用其列表中单元格的迭代器),但是这一行:

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

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

++obj

这里,obj是迭代器,它只是在AdjustGridCoord的调用中被无效并且它的指示单元被删除了。这导致访问被释放的内存,这正是valgrind所抱怨的。

你基本上有两个选择:

  1. 重新构造循环,以便在调用AdjustGridCoord之前获得后续迭代器
  2. 遍历列表一次并记录您需要在其他数据结构中进行的更改,然后对该次要“更改列表”结构执行第二次循环,并在该循环内实际对这些更改进行原始列表。
  3. 2的示例是创建一个std::vector<std::pair<unsigned int, unsigned int> >,其中包含您需要调用AdjustGridCoord的坐标,然后对其进行迭代以实际进行调用。

答案 1 :(得分:1)

12个free'd的块实际上是列表节点,而不是你的对象。因此,std::list::remove()没有在您的指针上调用delete,只是delete包含它的列表节点。

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