【问题标题】:omnet++ : self message as disposed objectomn​​et++:作为已处置对象的自我消息
【发布时间】:2017-02-15 15:34:35
【问题描述】:

模拟运行但在控制台中我有这个注释。

未处理的对象:(omnetpp::cMessage) Mysimulation.Switch4.eth[2].queue.scheduler.IntervalTimemsg -- 检查 模块析构函数未处理的对象:(omnetpp::cMessage) Mysimulation.Switch5.eth[1].queue.scheduler.IntervalTimemsg -- 检查 模块析构函数

实际上这是我通过模拟一遍又一遍地使用两个计时消息创建的模块。上网看了下,发现这个错误与创建的对象在应该删除的时候没有被删除有关。

void PriorityScheduler::initialize() {
gateCycleTimemsg = new cMessage("gateCycleTimemsg"); 
scheduleAt(baseTime , gateCycleTimemsg); 
// baseTime = 2s
}

void PriorityScheduler::handleMessage(cMessage *msg) {
   if (msg == gateCycleTimemsg) {

      if (currentList == (lastIntervalTime)) {  
      delete msg; 
      gateCycleTimemsg = new cMessage("gateCycleTimemsg");     
      scheduleAt( simTime() + gateCycleTime , gateCycleTimemsg); 
      ...
      IntervalTimemsg = new cMessage("IntervalTimemsg");
      scheduleAt( simTime() + Interval , IntervalTimemsg);
      }

      else if (currentList == (firstIntervalTime)) {
      gateCycleTimemsg = msg;    // same message reused
      scheduleAt(simTime() + gateCycleTime , gateCycleTimemsg); 
      //gateCycleTime = 10 seconds
      ...
      IntervalTimemsg = new cMessage("IntervalTimemsg"); 
      scheduleAt( simTime() + Interval , IntervalTimemsg); 
      // Interval = 1s
      }
  }

  else if (msg == IntervalTimemsg) {
       if (currentList == (lastIntervalTime));    
       else{
       IntervalTimemsg = msg;                 
       scheduleAt( simTime() + Interval , IntervalTimemsg);
       }
}

插件路径:/home/amr/omnetpp-5.0/samples/etc/plugins;./plugins 在抛出一个实例后调用终止 'omnetpp::cRuntimeError' what(): 对象 pk-56-145 当前在 (omnetpp::cEventHeap)simulation.scheduled-events,它不能 删除。如果在 omnetpp::cEventHeap 内部发生此错误,则需要 更改为在删除该对象之前调用 drop()。如果这 omn​​etpp::cEventHeap 的析构函数内部发生错误,而 pk-56-145 是 类成员 omnetpp::cEventHeap 需要在 析构函数

我创建了一个构造函数和析构函数。在网上阅读解决方案后,我还创建了函数 finish()。这仍然没有解决它。

我还删除了收到的每条消息并在发送时创建了一条新消息,但它没有改变任何东西。

编辑:我用删除味精编辑了编码;我添加并给出了时间示例并添加了以下部分,

BaseTime 'BT',gateCycleTime 'CT',间隔 'IT'

----> BT              
         <---- IT1 ----> <----- IT2 ----> .........<-------- ITx -------->    
         <------------------------------ CT ----------------------------->

我对 BT 和 CT 使用了相同的消息,而对 IT 使用了另一条消息,因为我不知道最后一个 IT 'ITx' 的时间。

【问题讨论】:

    标签: omnet++


    【解决方案1】:

    您正在创建新的计时器(消息),但从不删除旧的计时器。在处理消息时简单地删除消息是行不通的(因此出现错误消息)。

    我的建议(对您的模拟一无所知):

    1. 在初始化函数中创建一次计时器消息(例如)
    2. if (msg == gateCycleTimemsg)-->检查定时器消息是否已经调度
    3. 如果定时器消息已经被调度,取消定时器并重新调度它,但不要创建一个新的
    4. 如果没有安排计时器,安排(创建)它(显然是第一次)
    5. for else if (msg == IntervalTimemsg) --> 当计时器到期(自我消息已传递)时调用它,因此只需重新安排计时器但不创建新消息。

    您可以在 OMNeT++ 手册中阅读更多关于自我消息(通常用于计时器)的信息:https://omnetpp.org/doc/omnetpp/manual/#sec:simple-modules:self-messages

    【讨论】:

    • 嗯,我看了文档,还是解决不了。我有两个时间不是并行的问题。因此,如果我没记错的话,使用delete msg; 会删除两者。导致139错误码
    • 首先,删除handleMessage 中的消息而不破坏函数本身是危险的,因为其他if (msg == ...) 检查将失败,因为您删除了该消息。其次,两个计时只是两个定时器,你不要删除一个定时器,如果定时器的条件在它结束之前发生变化(超时)你就取消它。对两个计时器使用相同的消息可能会使您感到困惑,而不是帮助。为每个计时器使用单独的计时器消息,在必要时创建它们并在必要时取消或重新安排它们。可能只需要在析构函数中删除。
    【解决方案2】:

    一般来说,handleMessage()函数中不应该创建定时器,以避免在每次调用中创建和销毁对象。因此,初始化函数应该创建消息

    void PriorityScheduler::initialize() {
        gateCycleTimemsg = new cMessage("gateCycleTimemsg");
        IntervalTimemsg = new cMessage("IntervalTimemsg");
        scheduleAt(baseTime , gateCycleTimemsg); 
    }
    

    finish 函数或析构函数应该清理它们。

    void PriorityScheduler::finish() {
        cancelAndDelete(gateCycleTimemsg);
        cancelAndDelete(IntervalTimemsg);
    }
    

    【讨论】:

    • 非常感谢,但我已经提到我创建了完成以及析构函数和构造函数。将消息设置为 nullptr 的析构函数和构造函数会给出错误 137 或 139,但 finish() 不会,除非我已经在代码中有 cancelEvent() 或 CancelanDelete()。
    【解决方案3】:

    排队

    IntervalTimemsg = new cMessage("IntervalTimemsg"); 
    

    您每次都创建cMessage 对象的一个新实例,并将指向它的指针写入IntervalTimemsg。但是,您永远不会删除由IntervalTimemsg 指示的对象。结果,当第二次(和另一次)执行此行时:

    • 在内存中创建了一个新对象
    • 指向前一个对象的指针丢失了
    • 之前的对象仍然存在于内存中

    因此finish() 中的cancelAndDelete(IntervalTimemsg) 只会删除最后一个对象

    建议的解决方案:

    1. 在构造函数中添加:

      IntervalTimemsg = nullptr;
      
    2. 换行:

      IntervalTimemsg = new cMessage("IntervalTimemsg"); 
      

      进入:

      if (IntervalTimemsg != nullptr) {
         cancelAndDelete (IntervalTimemsg);
      }
      IntervalTimemsg = new cMessage("IntervalTimemsg"); 
      

    【讨论】:

    • 我已经有了你说的构造函数和析构函数。它也有效,但我仍然不明白最后一步,1 我在每次安排之前添加了cancelEvent(xxxx);2 我只创建了每条消息一次,一个是初始消息,另一个是它只能工作一次的条件。我没有得到 3 if (msg == gateCycleTimemsg) { gateCycleTimemsg = msg; scheduleAt( simTime() + gateCycleTime , gateCycleTimemsg); scheduleAt( simTime() + Interval , IntervalTimemsg); 已经收到 intervalTimemsg 和后来的 gateCycleTimemsg。
    • 1) cancelEvent() 只从未来事件集中删除一条消息,它不会删除内存中的任何对象 2 ) 在您的代码中,每次在收到gateCycleTimemsg 时都会创建一个名为IntervalTimemsg 的新cMessage,毫无疑问它不止一次 . 3) IntervalTimemsg = msg; 行是不必要的,因为msg 已经等于IntervalTimemsg
    猜你喜欢
    • 2019-03-16
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多