1

我会很感激帮助调试多集容器的一些奇怪行为。有时,容器似乎停止排序。这是一个罕见的错误,很长一段时间后仅在一些模拟中才明显,而且我缺乏想法。(我是一个业余程序员——欢迎各种建议。)

我的容器是一个std::multiset包含Event结构的容器:

typedef std::multiset< Event, std::less< Event > > EventPQ;

结构Event按其double time成员排序:

struct Event {

 public:
explicit Event(double t) : time(t), eventID(), hostID(), s() {}
Event(double t, int eid, int hid, int stype) : time(t), eventID( eid ), hostID( hid ), s(stype) {}

  bool operator < ( const Event & rhs ) const {
    return ( time < rhs.time );
  }

  double time;
  ...
};

该程序迭代通过将具有无序时间的事件添加到EventPQ currentEvents然后按顺序拉出事件的周期。很少,在添加了一些事件之后(具有完全“合法”的时间),事件开始无序执行。

是什么导致事件无法正确排序?(或者什么会弄乱迭代器?)我已经检查了所有添加的事件时间都是合法的(即,都超过了当前的模拟时间),并且我还确认了错误不会发生,因为两个事件恰好被安排同时。

我很想就如何解决这个问题提出建议。

执行和添加事件的代码如下:

  double t = 0.0;
  double nextTimeStep = t + EPID_DELTA_T;
  EventPQ::iterator eventIter = currentEvents.begin();

while ( t < EPID_SIM_LENGTH ) {

     // Add some events to currentEvents

     while ( ( *eventIter ).time < nextTimeStep ) { 

         Event thisEvent = *eventIter;
     t = thisEvent.time;
     executeEvent( thisEvent );
     eventCtr++;
     currentEvents.erase( eventIter );
     eventIter = currentEvents.begin();

  }

  t = nextTimeStep;
  nextTimeStep += EPID_DELTA_T;
}


void Simulation::addEvent( double et, int eid, int hid, int s ) {
  assert( currentEvents.find( Event(et) ) == currentEvents.end() );

  Event thisEvent( et, eid, hid, s ); 
  currentEvents.insert( thisEvent );
}

我应该补充一点,有时一个事件在执行时会从currentEvents. 这是用

double oldRecTime = 10.0; // gets defined legitimately in simulation
EventPQ::iterator epqItr = currentEvents.find( Event(oldRecTime) );
assert( currentEvents.count( Event(oldRecTime) ) == 1 );
currentEvents.erase( epqItr );

即使这段代码看起来不错,我也想知道其他可以检查发生了什么的方法——我目前正在使用很多 asserts() 和 cout << 检查。

4

3 回答 3

1

您的事件处理周期无法检查队列是否为空。否则,一切看起来都很好(或多或少)。

但是,如果队列中的事件用完currentEvents,则行为未定义。它可能表现为某种东西,表现为事件被无序处理。

事实上,我看到的一些关联容器的实现用“虚拟循环”数据结构来表示它们,从某种意义上说,如果你忽略受控序列的结尾并继续迭代,你的迭代器将出现在序列的开头。你的情况可能是这样的吗?

与您的代码相关的另一个问题是:如果新事件以time小于“当前”时间的值进入队列,会发生什么?我没有看到任何可以在您的代码中捕获这种情况的检查。显然,如果发生这种情况,即如果某些事件“来得太晚”,那么无论您如何实现它,它们都可能很容易被乱序处理。

于 2010-05-17T19:07:20.333 回答
1

如果可能的话,我建议将double您用作某些整数类型的键更改为。a setor的键multiset需要严格的弱排序——并且 a (通常)double不满足该要求(任何其他 IEEE 浮点类型也不满足)

于 2010-05-17T19:08:30.547 回答
0

在模拟中,我评论过

// Add some events to currentEvents

事件被添加到 currentEvents。(希望这很清楚。)如果添加了恰好属于队列顶部的事件,我相信它会弄乱指向 currentEvents.begin() 的迭代器。我在内部 while 循环之前立即重置了迭代器,并且事情似乎正常工作。

如果这不是解决方案,或者如果我在这里有其他问题,我会更新这个问题。

感谢所有评论的人;它帮助我了解我应该如何解决这些问题。

于 2010-05-17T20:42:47.287 回答