You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++多线程下使用dynamic_cast转换派生类对象出现数据异常问题

问题根因

你存储到list_fifoGroundEvt队列中的是对象的裸指针,该指针指向的对象生命周期提前结束,导致后续读取时访问的是已经被释放的野内存,出现数值异常:

  • 你调用pushGroundEventFifo(entry)时,若entry是栈上分配的局部临时对象,执行push操作时对象还未销毁,因此断点能看到正确的x、y值;
  • 当创建entry的函数执行完成后,栈空间被回收,entry被销毁,队列中存储的指针变成野指针,后续transmit线程读取该指针指向的内存时,内存已经被其他数据覆盖,因此读出来的y值异常。

解决方案

修改对象分配方式,改为堆分配延长对象生命周期,或者改用智能指针自动管理内存:

方案1:堆分配对象(基础修改)

创建entry时使用new在堆上分配内存,避免栈回收导致对象销毁,示例调用逻辑:

// 原来的栈分配写法(错误):
// fifoGroundEvtEntry entry;
// entry.x = 1;
// entry.y = 2;
// sender::GetInstance()->getDataCollector()->pushGroundEventFifo(entry);

// 修改为堆分配写法(正确):
fifoGroundEvtEntry* entry = new fifoGroundEvtEntry();
entry->x = 1;
entry->y = 2;
sender::GetInstance()->getDataCollector()->pushGroundEventFifo(*entry);

注意要在test方法读取完数据后,手动delete指针避免内存泄漏,修改test方法:

void test() {
    if (fifoGroundEvtEntry* grdEvt = dynamic_cast<fifoGroundEvtEntry*>(list_fifoGroundEvt.front()))
    {
        std::cout << grdEvt ->y << std::endl;
    }
    delete list_fifoGroundEvt.front(); // 新增:释放堆内存
    list_fifoGroundEvt.pop_front();
}

方案2:使用智能指针(更安全,避免内存泄漏)

修改队列存储类型为std::shared_ptr<fifoEvtEntry>,自动管理对象生命周期,无需手动释放内存:

// 修改collector类的队列定义:
private:
    std::list<std::shared_ptr<fifoEvtEntry>> list_fifoGroundEvt;

// 修改push方法:
void pushGroundEventFifo(std::shared_ptr<fifoEvtEntry> entry) {
    if (auto grdEvt = std::dynamic_pointer_cast<fifoGroundEvtEntry>(entry))
    {
        list_fifoGroundEvt.push_back(grdEvt);
    }
}

// 调用示例:
auto entry = std::make_shared<fifoGroundEvtEntry>();
entry->x = 1;
entry->y = 2;
sender::GetInstance()->getDataCollector()->pushGroundEventFifo(entry);

其他注意事项

如果后续逻辑改为线程运行过程中同时有push操作,需要给list_fifoGroundEvt的读写操作加互斥锁,避免多线程竞争导致的异常。

内容的提问来源于stack exchange,提问作者anes47

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 19:54:04