Qt程序crash信息的捕捉与跟踪(qt-mingw)在⽤qt编写程序时经常会遇到崩溃问题,如果抓取不到crash堆栈信息就会对崩溃问题束⼿⽆策,只能对其进⾏复现,推断。
⽬录
⼀般解决crash问题时有如下步骤:
1. 从软件发⾏版本能跟获得debug信息,在不同平台下有不同的表现⽅式,⽬前只讨论qt-mingw⽅式,这种⽅式可以利⽤修改⼯程⽂件
配置项编译时讲debug信息加⼊应⽤程序当中;当然这会增加发⾏版应⽤程序的体积。如果想体积变⼩可以strip应⽤程序。
2. 获得crash堆栈信息
3. 根据crash堆栈信息和1中的debug信息来查软件崩溃的位置。
如何执⾏以上3步骤,下⾯我详细介绍如何操作;
步骤1:
在⼯程⽂件.pro中加⼊如下代码,⽣成可执⾏⽂件中就会带debug信息:
QMAKE_CXXFLAGS_RELEASE += -g
QMAKE_CFLAGS_RELEASE += -g
QMAKE_LFLAGS_RELEASE = -mthreads -Wl
前两⾏意识意思为在release版本中增加debug信息;第三⾏意思为release版本中去掉-s参数,这样就⽣成对应符号表,可以调试跟踪;步骤2:
(注:⽬前只讨论windows平台,linux和mac暂不讨论;)
需要调⽤window平台系统api进⾏截取crash信息及获得crash堆栈。
⾸先在main函数中调⽤系统API SetUnhandledExceptionFilter,该函数有个设置回调函数,软件崩溃时会回调该系统函数,并传回崩溃地址信息等。
如何调⽤,请看如下代码:
long __stdcall  callback(_EXCEPTION_POINTERS*  excp)
{
CCrashStack crashStack(excp);
QString sCrashInfo = crashStack.GetExceptionInfo();
QString sFileName = "testcrash.log";
QFile file(sFileName);
if (file.open(QIODevice::WriteOnly|QIODevice::Truncate))
{
file.Utf8());
file.close();
}
qDebug()<<"Error:\n"<<sCrashInfo;
/
/MessageBox(0,L"Error",L"error",MB_OK);
crash是什么意思QMessageBox msgBox;
msgBox.setText(QString::fromUtf8("亲,我死了,重新启动下吧!"));
<();
return  EXCEPTION_EXECUTE_HANDLER;
}
int main(int argc, char *argv[])
{
SetUnhandledExceptionFilter(callback);
QApplication a(argc, argv);
Dialog w;
w.show();
();
}
注:CCrashStack 是我写的类,⽬的是调⽤系统API获取crash堆栈信息;(⽬前只针对windows平台)
步骤3:
通过qt命令⾏进⼊ 执⾏命令:
objdump - >aaa.asm
命令执⾏完成后,根据步骤2中获得的crash堆栈信息在aaa.asm中查响应地址,即可得到崩溃具体位置。
附件为测试demo,⾥⾯有完整代码,各位可下载体验。
Demo下载地址:
⽹友评论:
EXE太⼤,asm⽣成不全,怎么解决? asm⽣成到465350⾏就不写了(8个⽉前#7楼)收起回复
您好,我直接编译您的代码,在release下编译遇到该问题: g++: error: unrecognized command line option '-Wl' 我的环境是Qt
4.8.6,使⽤mingw编译的。请问我是否还有什么没有地⽅没有设置正确呢?(3年前#6楼)收起回复
回复 振星: stackoverflow/questions/22282871/unrecognized-command-line-option-wi
stackoverflow/questions/21305309/g-doesnt-recognize-the-option-wl 我也碰到了,将那三⾏加⼊⼯程后release编译报错,根据第⼆篇讨论的答案,我去掉-Wl之后编译OK,后⾯⼜实验了下-Wl后⾯加逗号也可以并且两种编译出的exe
md5⼀样,不知道实际编译-Wl参数到底有没有进去,不过感觉后⾯加逗号应该妥当⼀点 QMAKE_LFLAGS_RELEASE = -mthreads -Wl, 或者 QMAKE_LFLAGS_RELEASE = -mthreads(1年前)
命令执⾏完成后,根据步骤2中获得的crash堆栈信息在aaa.asm中查响应地址,即可得到崩溃具体
位置 能否做个说明,是怎么到具体位置的,log⽂件,asm⽂件我都有了,不知道怎么看,谢谢(4年前#5楼)收起回复举报回复
回复 叹逍遥: 上⾯两段分别是记录的crash⽇志和dump出的asm, Exception Addr: 00401E20 说明代码地址00401E20出发⽣异常,Write Address: 00000000说明异常的时候正在访问0x00000000内存地址,对⽐asm中00401E20处,正好是博主构造的对空指针进⾏写⼊的异常处。剩下的Registers和Call Stack保存了现场的寄存器和堆栈信息。 不过有个问题是这东西release版本带着调试信息发布,很容易被⼈看出源码,不过⾃⼰写的⼩程序⽆所谓了 末尾感谢博主的分享!(1年前)
回复 fanweimianA: 虽然时间挺久了,但是⾃⼰折腾了好长时间忍不住回复⼀下: Exception Addr: 00401E20 Module: D:\QT\build-TestCrash-Desktop_Qt_5_8_0_MinGW_32bit-Release\ Exception Code:
C0000005 Write Address: 00000000 Instruction: C7 05 00 00 00 00 00 00 00 00 0F 0B 90 90 90 90 Registers: EAX: 00000000 EBX: 00000000 ECX: 0077FE04 EDX: 00000000 ESI: 0077D428 EDI: 0077FE04 ESP:
0077D31C EBP: 0077D408 EIP: 00401E20 EFlags: 00010246 Call Stack: 00401E20 D:\QT\build-TestCrash-Desktop_Qt_5_8_0_MinGW_32bit-Release\ 620C2D1F
C:\Qt\5.8\mingw53_32\bin\Qt5Widgets.dll void Dialog::on_btnTestCrash_clicked() { int *p = NULL; *p = 4; 401e20: c7 05 00 00 00 00 00 movl $0x0,0x0 401e27: 00 00 00 401e2a: 0f 0b ud2 401e2c: 90 nop 401e2d: 90 nop 401e2e: 90 nop 401e2f: 90 nop 00401e30 <__ZL7sprintfPcPKcz>: }(1年前)
你好。这个信息时怎么对应的?(4年前#4楼)
命令执⾏完成后,根据步骤2中获得的crash堆栈信息在aaa.asm中查响应地址,即可得到崩溃具体位置 能否做个说明,是怎么到具体位置的,log⽂件,asm⽂件我都有了,不知道怎么看,谢谢(4年前#3楼)
1.mingw
2.mingw下⽣成的符号和应⽤程序⽂件是⼀起的;通过objdump命令可以产⽣出符号⽂件;例如: objdump -
>a.asm(4年前#2楼)
你好,问两个问题 1.你给的这个demo的编译环境是什么,mingw还是msvs? 2.步骤1中的⽣成的符号⽂件在哪⾥? 谢谢(4年前#1楼)收起回复
回复 yanan_gd: 1.mingw 2.mingw下⽣成的符号和应⽤程序⽂件是⼀起的;通过objdump命令可以产⽣出符号⽂件;例如:objdump - >a.asm(4年前)

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。