0

我有一个单线程程序,在使用 valgrind 运行时显示大小为 4 的无效读取错误。

    void
 AccountStatus::transmitUpdate(int aiTuples, std::string& astrAliasPidf)
 {
  std::string lstrPidf;

  for (int i=0; i < TOTAL_TUPLE_COMBOS; i++)
  {
    if (_mSubList[i] != NULL)
    {
      GuidSubHandlerMap *subHandlerMap = _mSubList[i];

      if (this->getPidf (lstrPidf, i+1, aiTuples, astrAliasPidf, false) == -1)
        continue;

      ACE_DEBUG ((LM_DEBUG, ACCTPRES_DEBUG
        "transmitUpdate - created pidf for excludeMask [%X] with tuples [%X]\n", i+1, aiTuples));

      GuidSubHandlerMapIter iter;
      for (iter = subHandlerMap->begin(); iter != subHandlerMap->end(); iter++) //this line is shown as invalid read
      {
    subHandlerPtr lpHandler = iter->second;
    if (lpHandler)
    {
      lpHandler->queueNotify (CONTENT_TYPE, lstrPidf);
    }
  }
}
}
 }

在 valgrind 中显示为具有释放迭代器的函数如下,

    void
 AccountStatus::removeSubscription (const char *apcSubId, subHandlerPtr apHandler)
 {
  if (apcSubId && apHandler)
  {
    int excludeMask = apHandler->excludeMask();
    if (excludeMask != 0)
    {
      if (_mSubList[excludeMask-1] != NULL)
      {
        GuidSubHandlerMap *subHandlerMap = _mSubList[excludeMask-1];

        GuidSubHandlerMapIter iter = subHandlerMap->find (apcSubId);
        if (iter != subHandlerMap->end())
        {
          ACE_DEBUG ((LM_DEBUG, ACCTPRES_DEBUG
            "removeSubscription - [%s] mask [%X]\n", apcSubId, excludeMask));

          subHandlerMap->erase (iter); //this is where valgrind is showing memory being freed
        }
      }
    }
  }
 }

Valgrind输出如下,

    ==9130== Invalid read of size 4
==9130==    at 0x9566CC: std::_Rb_tree_increment(std::_Rb_tree_node_base*) (in /usr/lib/libstdc++.so.6.0.8)
==9130==    by 0x23A954CD: std::_Rb_tree_iterator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >::operator++(int) (stl_tree.h:190)
==9130==    by 0x23AB4E01: ACCOUNT_PRESENCE::AccountStatus::transmitUpdate(int, std::string&) (accountStatus.cpp:518)

==9130==  Address 0x13604894 is 12 bytes inside a block of size 28 free'd
==9130==    at 0x400668A: operator delete(void*) (vg_replace_malloc.c:480)
==9130==    by 0x23A9647E: __gnu_cxx::new_allocator<std::_Rb_tree_node<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > > >::deallocate(std::_Rb_tree_node<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >*, unsigned int) (new_allocator.h:94)
==9130==    by 0x23A964B3: std::_Rb_tree<std::string, std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> >, std::_Select1st<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >, std::less<std::string>, std::allocator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > > >::_M_put_node(std::_Rb_tree_node<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >*) (stl_tree.h:362)
==9130==    by 0x23A96513: std::_Rb_tree<std::string, std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> >, std::_Select1st<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >, std::less<std::string>, std::allocator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > > >::destroy_node(std::_Rb_tree_node<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >*) (stl_tree.h:392)
==9130==    by 0x23A97F67: std::_Rb_tree<std::string, std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> >, std::_Select1st<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >, std::less<std::string>, std::allocator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > > >::erase(std::_Rb_tree_iterator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >) (stl_tree.h:1189)
==9130==    by 0x23A97FA1: std::map<std::string, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler>, std::less<std::string>, std::allocator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > > >::erase(std::_Rb_tree_iterator<std::pair<std::string const, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler> > >) (stl_map.h:446)
==9130==    by 0x23AB5515: ACCOUNT_PRESENCE::AccountStatus::removeSubscription(char const*, std::tr1::shared_ptr<ACCOUNT_PRESENCE::subHandler>) (accountStatus.cpp:314)

正如我提到的程序是单线程的,我不知道为什么会出现这个错误。有人可以帮我解决可能导致这种情况的原因吗?

谢谢

4

1 回答 1

1

你没有显示完整的代码,所以很难说,但你应该尽量避免修改你正在迭代的容器。

如果您看到此参考页面,您会注意到这一行:

对已擦除元素的引用和迭代器无效。其他引用和迭代器不受影响。

因此,在您调用erase指向已擦除元素的迭代器后不再有效,这意味着您不能再使用 eg iter++

于 2012-08-31T05:03:34.307 回答