-3

我遇到了这个奇怪的问题,下面是正常工作的代码片段。

std::multimap<long,int>::iterator dateItr = reconnQueueDates.begin();

while( dateItr!=reconnQueueDates.end()  ){
LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
if(dateItr->first <= cDateTime){
    long nextTimeout = -1;
   if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1){

        if(nextTimeout>0){
       reconnQueueDates.insert(std::pair<long , int>(nextTimeout, dateItr->second));
            }
            reconnQueueDates.erase(dateItr);
     LOG_DEBUG("modified the iterator ressetting");
     dateItr = reconnQueueDates.begin();
     LOG_DEBUG("resset iter");
   }//end of callreconnect if
}else{
 ++dateItr;
} //else for datetime check
 }//end of while

在此之前,我在循环中使用带有 ++dateItr 的 for 循环,如下所示

 for( ;dateItr!=reconnQueueDates.end();++dateItr  ){
LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
if(dateItr->first <= cDateTime){
   long nextTimeout = -1;
   if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1){


            if(nextTimeout>0){
       reconnQueueDates.insert(std::pair<long , int>(nextTimeout, dateItr->second));       
             }
             reconnQueueDates.erase(dateItr);

        LOG_DEBUG("modified the iterator ressetting");
    dateItr = reconnQueueDates.begin();
    LOG_DEBUG("resset iter");
   }// callReconnect 
} // check datetime

 }// for loop

在调试时,我发现在循环内更改映射后,for 构造内的迭代器值仍在使用旧地址。

我正在使用 ubuntu 12.04 和 g++ 版本 4.6.3。在我看来,这是某种编译器错误或某种优化。

任何想法可能是哪个标志或错误。

4

1 回答 1

2

reconnQueueDates.erase(dateItr);迭代器dateItr无效并且对它的任何使用都是未定义的行为之后。由于您的旧循环和新for循环都在之后使用它,因此您的新版本“有效”这一事实纯属偶然。

正确的做法是在擦除该元素之前首先提取您可能仍需要的所有数据(包括下一个迭代器的位置)。例如:

std::multimap<long,int>::iterator dateItr = reconnQueueDates.begin();

while( dateItr!=reconnQueueDates.end()  )
{
  LOG_DEBUG("RUN comparision " <<cDateTime<< ", "<<dateItr->first);
  if(dateItr->first <= cDateTime)
  {
    std::multimap<long,int>::iterator nextItr = dateItr;
    ++nextItr;
    long nextTimeout = -1;
    if( (nextTimeout = callReconnects(dateItr->second,dateItr->first))>-1)
    {
      std::pair<long , int> newentry = std::make_pair(nextTimeout, dateItr->second);
      reconnQueueDates.erase(dateItr);
      if(nextTimeout>0)
      {
        reconnQueueDates.insert(newentry);
      }
      LOG_DEBUG("modified the iterator resetting");
      nextItr = reconnQueueDates.begin();
      LOG_DEBUG("reset iter");
    }//end of callreconnect if
    dateItr = nextItr;
  }
  else
  {
    ++dateItr;
  } //else for datetime check
}//end of while
于 2012-10-20T08:21:21.077 回答