QT程序出现Bus Error问题的调试
2012-08-08 12:52
309 查看
QT程序出现Bus Error问题的调试
1.文档目的
本文档目的在于探究部分QT程序在嵌入式板子上出现BusError问题的调试及解决方法;以数码相框程序出现的BusError为例;
2.原因分析
2.1产生BusError的可能原因:BusError即总线错误,BusError通常都是因为非对齐访问造成的。CPU在设计上为了性能上的考虑,要求待访问,操作的数据地址都要对齐。如果发现没有对齐的访问,就会向当前进程发出SIGBUS信号,使程序崩溃。RISC包括MIPS都是这种类型的芯片。而X86架构就没有这种对齐要求。所以代码在嵌入式环境下有总线错误而在X86下面可能就没有问题,当然这是有性能的代价。
BusError的产生除了上边提到的访问数据地址对齐问题之外,还可能是因为一下原因:
1机器物理问题或者访问无效物理地址,但这种情况非常少见。
2Linux平台上执行malloc(),如果没有足够的RAM,Linux不是让malloc()失败返回,
而是向当前进程分发SIGBUS信号。
3某些架构上访问数据时有对齐的要求,比如只能从4字节边界上读取一个4字节的数据类型。IA-32架构没有硬性要求对齐,尽管未对齐的访问降低执行效率。另外一些架构,比如SPARC、m68k,要求对齐访问,否则向当前进程分发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出现的原因是硬件上、底层软件上或者确实是程序本身的原因,所以此文档有待补充。
相关文章推荐
- QT程序出现Bus Error问题的调试
- QT程序出现Bus Error问题的调试
- 解决vc++DEBUG ERROR问题前几天师弟调试程序的时候出现了这样一个错误,出错的位置是在delete [] 一个动态分配的数组时出现的。 经过调查发现错误是因为他之前在给数组赋值的时候越界了
- Qt Creator新安装后运行一个程序后,出现错误:Error while building/deploying project dict-qt (kit: Desktop Qt 5.10.0 MinGW 32bit) When executing step "qmake"
- visual studio 2010 出现问题,不能设置断点调试了,一运行就未响应,然后程序退出
- 在学习QT过程中调试slot出现的问题
- C++2005中调试出现问题。程序没错误,但调试时却出现无法找到调试信息
- Qt程序Release版出现 类似 QEventLoop: Cannot be used without QApplication 问题的终极解决方案
- 解决ASUS F8安装XP/2003系统后,Splendid程序出现“uiVista failed error 2”的问题
- 在Ubuntu 12.04 alternate 64位 中开发Qt程序出现/usr/bin/ld: error: cannot find -lGL
- 关于QT程序中出现"collect2: ld returned 1 exit status"的调试
- 如运行程序时出现 "Error establishing socket" 错误,则应进行如下调试:
- android 程序调试出现source not found的问题
- [Invalid postback or callback argument]昨晚调试程序时出现的问题,MARK一下
- VS2010调试“正试图在 OS 加载程序锁内执行托管代码”和运行出现R6034问题解决
- 关于 qt程序退出出现“已停止工作”程序奔溃问题 的解决方法
- eclipse下使用Genymotion调试Android程序出现的问题
- 【GCC调试程序C语言问题】error: initializer-string for array of chars is too long [-fpermissive]
- 【经验随笔】Java程序远程调试定位特定运行环境上出现的问题
- 今天调试一个WebPart的简单程序出现的问题