-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 コンストラクト内の反復子の値がまだ古いアドレスを使用していることがわかりました。

g++バージョン4.6.3でubuntu 12.04を使用しています。ある種のコンパイラのバグか、これを行うある種の最適化のように思えます。

どのフラグまたはバグである可能性があるかについての考え。

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 に答える