日期:2014-05-16  浏览次数:21233 次

遇到"Unhandled exception in app.exe (QTGUID4.DLL): 0xC0000005: Access Violation"错误的解决过程

起因:

前几天,在没有稳定版本的基础上增加了一个功能,结果程序经常无情的崩溃了。

现象:

调试的时候崩溃,提示“Unhandled exception in app.exe (QTGUID4.DLL): 0xC0000005: Access Violation”,会调到Label的setEnabled处;

屏蔽掉相关代码之后,再次运行,会跳到Button的setPalette处;

屏蔽掉相关代码之后,再次运行,又会调到Label的setText处;

屏蔽掉相关代码之后,再次运行,会跳到一个vector变量的at(i)处。

这个屏蔽了之后就可以了。

release的时候,不固定的崩溃,日志报告为常见的debug信息:

Warning: Qt has caught an exception thrown from an event handler.

Throwing exceptions from an event handler is not supported in Qt.

You must reimplement QApplication::notify() and catch all exception there.

重现:

经常性的,虽然时间不固定,但是很容易重新(想不重现都不行)。

调试:

如果使用try()catch(...)来讲问题代码封闭,调试时会崩溃到Qt内核。

想上网上找找吧,错误不明显,网速也慢的难受,只好自己闷骚了。

思考:

想来想去,大概有这么几个会导致崩溃的地方:

1、使用了不当的指针,导致系统变量乱套了。不过也不太可能,一个变量乱套可以,总不至于A、B、C、D都乱套吧。

2、系统使用了QTimer定时器,但是使用了长时间的延时。有可能阻碍主线程或串口线程动作,阻碍主线程解析串口数据缓冲区溢出,导致崩溃。

3、系统结果需要定时保存到本地Excel文件。可能是Excel模块出一些不太严重的问题,时间长了导致系统随机崩溃。

4、或者别人安装、卸载了什么软件,导致操作系统环境变化,影响了调试、运行环境,最终导致崩溃。

5、或者Qt本身环境不稳定。想想,也不太可能吧,毕竟已经十几年了,一般的应用应该没问题。要是真有问题,那真的恭喜我了。

回退到稳定版本:

稳定版本与现在的区别:

1、延时是200ms,现在的是4000ms。

2、增加了平均值输出功能,并引入了平均值数据存储变量(数组)。

3、界面有原来的20*1个按钮和20*4个标签扩展为30*1个按钮和30*4个标签。

逐步增加功能:

1、增加平均值输出功能,正常;看来不是因为引入新变量导致的。

2、增加界面按钮,正常;

3、增加延时,崩溃。

终于发现问题:

原来是延时过长引起崩溃。

主线程中使用的QTime定时器中循环造成程序线程堵塞:

void CDelayTimer::DelayTime(unsigned long nDelayTime)//ms
{
    QTime time;
    time.start();
    while (time.elapsed() < nDelayTime)
    {
        //空语句,延时效果
    }
}

按照Qt中文手册中7-3 系统繁忙时的响应( Staying Responsive During Intensive Processing的说明,改为如下可暂时使用:

void CDelayTimer::DelayTime(unsigned long nDelayTime)//ms
{
    QTime time;
    time.start();
    while (time.elapsed() < nDelayTime)
    {
        //空语句,延时效果
        QApplication::processEvents();
    }
}

结论:

其实个人感觉也可能不是这方面的原因,也可能是某个变量在定时器和主线程中同时写,造成变量写违例,引发这种问题。

但是现在还没有找到对应的位置。

思考:

1、一个延时时照顾其他事件的知识点:

        QApplication::processEvents();
2、多线程程序中定义、引入一个变量,要考虑作用范围,抱着“能不定义就不定义,能少定义就少定义”的原则。

  个人感觉如果对某个变量频繁修改,那么就要积极考虑是否会引起冲突,尽量降低维护成本。

3、构建能够调试的环境,步步跟踪。

  我的情况就是,开发机上可以调试,但是生产机上不能调试,郁闷的要死。

  在设置QWidget字体样式、变量内容被覆盖就无法调试。

遗留问题:

1、生产机上无法调试,还不知道是什么原因。

2、根本原因仍不明朗,暂时可用,但还需要继续研究。