QT程序出现Bus Error问题的调试

1.文档目的

本文档目的在于探究部分QT程序在嵌入式板子上出现BusError问题的调试及解决方法;

以数码相框程序出现的BusError为例;

2.原因分析

2.1产生BusError的可能原因:

BusError即总线错误,BusError通常都是因为非对齐访问造成的。CPU在设计上为了性能上的考虑,要求待访问,操作的数据地址都要对齐。如果发现没有对齐的访问,就会向当前进程发出SIGBUS信号,使程序崩溃。RISC包括MIPS都是这种类型的芯片。而X86架构就没有这种对齐要求。所以代码在嵌入式环境下有总线错误而在X86下面可能就没有问题,当然这是有性能的代价。

BusError的产生除了上边提到的访问数据地址对齐问题之外,还可能是因为一下原因:

1机器物理问题或者访问无效物理地址,但这种情况非常少见。

2Linux平台上执行malloc(),如果没有足够的RAMLinux不是让malloc()失败返回,
而是向当前进程分发SIGBUS信号。

3某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外一些架构,比如SPARCm68k,要求对齐访问,否则向当前进程分发SIGBUS信号。

SIGBUS与SIGSEGV(产生段错误Segmentfault)信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产生coredump

SIGBUS与SIGSEGV信号的一般区别如下:

1SIGBUS(Buserror)意味着指针所对应的地址是有效地址,但总线不能正常使用该
指针。通常是未对齐的数据访问所致。

2SIGSEGV(Segmentfault)意味着指针所对应的地址是无效地址,没有物理内存对
应该地址。

2.2数码相框产生BusError的调试:

经过查找资料:嵌入式板子上如果程序初始化运行无任何调试数据输出即马上出现BusError,则很大原因是由于交叉编译环境中的库和文件系统里库的不一致,或者编译的参数有问题之类的原因导致的非对齐访问数据地址。重新配置好编译参数及更新文件系统内的库一般都能解决问题;

而数码相框出现的BusError问题并不是上边提到的情况,而是当板上数码相框程序在运行后,自动播放图片并有特效切换时不定时间出现BusError,经过打印调试信息,并未定位到BusError出现的确定位置,但是分析调试信息,可定位到两个位置,其一为在定时器QTimer或者动画类QtimeLine触发的特效实现槽函数运行结束时出现,其运行结束后会调用系统的画图事件函数,然后数码相框在画图事件中实现图片的显示;另一个位置为在画图事件中实现填充区域的QPainter成员函数fillRect()时出现BusError

QT中QTimer类提供了定时器信号和单触发定时器。它在内部使用定时器事件来提供更通用的定时器。QTimer很容易使用:创建一个QTimer,使用start()来开始并且把它的timeout()连接到适当的槽。当这段时间过去了,它将会发射timeout()信号。而QtimeLine也有相同的机制。我们通过连接信号与槽函数,实现了时间间隔改变图片的显示,从而实现图片切换特效。

从实际出发,分析数码相框程序中代码的执行效率,可以发现数码相框从图片文件中加载数据到缓存,以及画图事件中图片的显示均需要占用系统大部分资源来实现,由于数码相框程序中为了实现比较流畅的特效,定时器及动画的间隔均设置的很短,时间约10ms~30ms出发一次画图,这时候便要求系统在这个时间间隔内能顺利的实现图片的显示,若在这个时间间隔内系统无法完全执行完画图事件,则定时到时间系统又重新调用槽函数进入画图事件,可能会导致重入的问题。

由于当系统试图访问一块无文件内容对应的内存区域,比如超过文件尾的内存区域,或者以前有文件内容对应,现在为另一进程截断过的内存区域则会发生BusError,那么可以猜测数码相框可能是由于函数重入问题导致的BusError,调试一下,先在数码相框中对定期器及动画类触发的槽函数做以下处理:定时器定时触发槽函数,进入槽函数关闭定时器,实现槽函数后再开启定时器,同理,动画类可以用暂停的方式;用此方法避免函数重入的问题,再交叉编译到板子上进行测试,发现程序稳定性有所提高,但是依然有BusError问题出现,分析调试信息,此时发现第一种情况出现BusError的问题得到解决,现在程序的BusError集中到第二个位置,即在画图事件中实现填充区域的QPainter成员函数fillRect()时出现BusError

分析QT源码,fillRect实现方式如下:

fillRect(r,Qt::SolidPattern);

--->

setBrush(Qt::SolidPattern);drawRect(r);

--->

inlinevoidQPainter::drawRect(constQRectF&rect)

{

drawRects(&rect,1);

}

--->

voidQPainter::drawRects(constQRect*rects,intrectCount)

{

}

QT源码中对于类的包装导致我们比较难分析出其如何具体操作硬件,而且并不是每一次执行此行代码都会导致BusError,故猜测可能程序某些客观存在的指针导致其实现fillRect偶然性出现未对齐的数据访问。故对于数码相框项目而言,我们暂时采取用其他方式填充屏幕区域:设置黑色背景图的方式,再经过测试,数码相框程序终于能比较稳定的运行了。

由于并未联系loongson1B开发板底层的实现来分析BusError,故并没有真正探究到BusError出现的原因是硬件上、底层软件上或者确实是程序本身的原因,所以此文档有待补充。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值