QTreeView与QAbstractItemModel展开节点时程序崩溃问题排查
动态层级模型展开崩溃问题分析与解决
场景与异常现象
- 需求:实现层级树形展示,节点展开时动态生成子节点,子节点数量不确定,部分可本地即时创建,部分需异步请求数据后生成
- 技术架构:基于
QTreeView+QSortFilterProxyModel+ 自定义QAbstractItemModel实现 - 异常表现:
- 启用
QSortFilterProxyModel代理时,功能完全正常 - 移除代理模型,直接让视图绑定自定义模型时,展开任意节点会触发错误码
-1073741819(0xC0000005)的内存崩溃
- 启用
临时修复方案
- 新增一个带
QueuedConnection的_populate_request信号,将fetchMore中的子节点增删逻辑从视图的展开调用栈中剥离,通过信号槽异步执行,崩溃问题解决 - 添加右键“Reload”菜单,用于验证子节点删除操作是否会引发同类崩溃
直接调用导致崩溃的原因
Qt的模型视图框架中,QTreeView在处理节点展开事件时,会同步调用模型的fetchMore方法,此时视图正处于内部状态维护(比如遍历节点、更新视图项)的流程中:
- 无代理模型时,视图与自定义模型直接交互,
fetchMore执行在视图的事件调用栈内,若此时直接调用beginInsertRows/endInsertRows修改模型结构,会导致视图当前持有的节点引用、遍历状态与模型实际数据产生冲突,触发内存访问违规(0xC0000005通常对应野指针或越界访问) - 启用
QSortFilterProxyModel时,代理模型会对原始模型的结构变更信号进行缓冲、转换,相当于在视图与原始模型之间增加了一层异步隔离,避免了调用栈内的直接状态冲突,因此不会崩溃
内容的提问来源于stack exchange,提问作者ser
相关产品推荐
相关产品推荐

