分享

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

 astrotycoon 2013-08-29

1.文档目的

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

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

2.原因分析

2.1 产生Bus Error的可能原因: 

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

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

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

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

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

SIGBUSSIGSEGV(产生段错误Segment fault)信号一样,可以正常捕获。SIGBUS的缺省行为是终止当前进程并产生core dump

SIGBUSSIGSEGV信号的一般区别如下:

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

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

2.2 数码相框产生Bus Error的调试: 

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

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

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

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

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

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

fillRect(r, Qt::SolidPattern);

--->

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

--->

inline void QPainter::drawRect(const QRectF &rect)

{

    drawRects(&rect, 1);

}

--->

void QPainter::drawRects(const QRect *rects, int rectCount)

{

    …

}

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

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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多