【开发日记】——在线程中使用容器崩溃问题
Qt 多线程 + 容器 遍历崩溃
提示:记录子线程中崩溃的原因
文章目录
- Qt 多线程 + 容器 遍历崩溃
- 一、核心铁律
- 二、代码建议
- 三、最容易忽略的隐形崩溃点(经验之谈)
- 四、排查此类问题
- 总结
一、核心铁律
- QVector / QList / QString 全都不是线程安全的
- 哪怕只做只读遍历,也不能让子线程直接访问主线程的容器
- 只要容器生命周期不归子线程控制,就一定会有崩溃风险
- 崩溃原因永远只有两个:
遍历中容器被销毁(野指针)
遍历中容器内存被重新分配(迭代器失效)
二、代码建议
- 主线程需要传参数给子线程中,使用值拷贝,不要使用引用,指针。
- 必须共用原数据时的开发,不使用拷贝(内存占用大),请使用线程锁(QMutex),将整个线程锁起
三、最容易忽略的隐形崩溃点(经验之谈)
你以为没修改,其实 Qt 已经偷偷改了:
- 容器赋值
- 容器非 const 传递给函数
- 容器被重新初始化
- 容器所在对象析构 / 关闭窗口
四、排查此类问题
将要迭代的容器先拷贝,然后再进行迭代
// 把for(autox:vec)// 改成autotmp=vec;for(autox:tmp)不崩了 =生命周期 / 迭代器失效问题
依然崩 =空指针 / 越界 / 其他 bug
总结
子线程不要直接访问主线程的容器,哪怕只读也不行;要么传拷贝,要么加锁。
QVector 只读遍历也会崩溃,因为生命周期和内存地址不可控
最优方案:传拷贝,简单、安全、无坑
必须共享:加锁,锁整个遍历过程
永远不要让子线程直接访问主线程动态变化的容器
