prepareGeometryChange()引发的崩溃

最近在处理了Qt绘图中的崩溃问题,问题出在了QGraphicsSceneFindItemBspTreeVisitor::visit()函数中,其原因是由于软件代码编写不规范及Qt图形视图框架的bug导致,先做如下总结。

1. 场景
系统在一定配置下,记录一段时间,执行初始化全部操作,软件崩溃,其崩溃堆栈信息如下:

 2. 分析
通过堆栈信息,可分析到此处有可能出现野指针的非法操作,但是由于堆栈信息不足,无法再做更详细的分析。
通过分析日志及代码流程梳理,复现出bug的崩溃场景,在PC端,有了更为详细的崩溃堆栈信息:

在上述堆栈信息中,发现异常操作出现在Qt图形视图框架的图元绘制过程中,我们再来看一下崩溃点附近的函数具体是在做什么。

崩溃点函数的功能是为了获取图元的顶层Item,此处操作代码逻辑简单,暂时无法分析出异常发生的原因。我们再来看看这个函数的调用点:

可以看出visit函数功能在于获取当前item列表的顶层Item去做一些处理,查看这些item列表,我们发现,这个列表中存在一些异常的item:

我们可以看到第15项之后的item都是野值,所以才导致了系统崩溃问题。因此,可以分析出,此处的item列表处于异常状态,那么问题就在于是什么导致图元列表异常。
通过查询相关资料,发现这是一个Qt的bug,官方给出的解决方案是:
Resolution: Always call prepareGeometryChange() before changing the item's geometry. Otherwise, the scene's index will fall out of sync, and the behavior is undefined.
再来看看Qt的帮助文档:

If you want to change the item's bounding rectangle, you must first call prepareGeometryChange(). This notifies the scene of the imminent change, so that it can update its item geometry index; otherwise, the scene will be unaware of the item's new geometry, and the results are undefined (typically, rendering artifacts are left within the view).
3. 结论:
由于在自定义图元移动或者boundingrect变化时,没有提前调用prepareGeometryChange(),导致场景内可能存在无效的item索引,在绘图过程中引发崩溃。

 

 

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值