我遇到了这个奇怪的问题,下面是正常工作的代码片段。
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。在我看来是某种编译器错误或某种优化方式。
知道它可能是哪个标志或错误。
答案 0 :(得分: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