嵌入式linux-arm系统中qt4程序添加core-dump日志(嵌入式设备qt程序卡屏黑屏问题排查)

为什么要添加core-dump日志

  1. 我们使用的是qt4.8版本,手动打印日志只有qInstallMsgHandler,这个打印堆栈信息是不能显示出现问题是在哪个类哪一行的,qt5往上使用qInstallMessageHandler是可以打印的,但是具体没有使用过。
  2. 我们qt程序在ubantu中使用qt creator开发好了之后交叉编译release包后放到linux-arm中,然后测试或者运行中会偶然产生进程直接挂掉或者屏幕卡屏或者是黑屏现象,只通过qt加入的手动日志不能排查问题。

为什么选择core-dump

1.这个qt程序挂掉无非就是编写程序内存溢出,数组下标越界等问题,所以第一次是想直接通过加入qInstallMsgHandler在关键节点打印相关信息,但是首先问题是偶现的,基本上没有重现;其次qInstallMsgHandler不能打印堆栈信息;最后是代码很多,在重新加入也不现实。
2.然后就选择整合了qBreakpad,生成dump文件,后缀.dmp文件,然后使用windbg/visual studio来解析文件查看,但是我们代码解析出来也是看不到代码异常堆栈信息。详细可以直接百度以下关键字:
Qt生成dump文件并定位bug
3.最后就选择了core-dump。

什么是 core dump (我度娘来的)

  1. core dump其实就是核心转储;核心转储是一个包含进程意外终止时进程内存内容的文件。核心转储由内核触发以响应程序崩溃。核心转储作为崩溃时程序状态的事后快照非常重要,特别是在故障难以重现的情况下。
  2. core dump 是Linux应用程序调试的一种有效方式,core dump又称为“核心转储”,是该进程实际使用的物理内存的“快照”。分析core dump文件可以获取应用程序崩溃时的现场信息,如程序运行时的CPU寄存器值、堆栈指针、栈数据、函数调用栈等信息。
    Core dump是Linux基于信号实现的。Linux中信号是一种异步事件处理机制,每种信号都对应有默认的异常处理操作,默认操作包括忽略该信号(Ignore)、暂停进程(Stop)、终止进程(Terminate)、终止并产生core dump(Core)等。
    3.以下情况会产生:
    内存访问越界 (数组越界、字符串无\n结束符、字符串读写越界)
    多线程程序中使用了线程不安全的函数,如不可重入函数
    多线程读写的数据未加锁保护(临界区资源需要互斥访问)
    非法指针(如空指针异常或者非法地址访问)
    堆栈溢出

具体实现步骤-测试是否生成 core dump

1.首先编写一个c++文件,一个空指针
test.cpp

#include <iostream>
using namespace std;
int main()
{
    cout << "Hello c++ start !" << endl;
    int temp = 1;
    int *pstr = &temp ;
    pstr = NULL;
    *pstr = 2;
     cout << "Hello c++ end !" << endl;
    return 0;
}

2.然后找到你qt creator的编译命令 我的是执行以下命令生成可执行文件

cp ./test.cpp /home/software/t113-linux/out/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi/bin
cd /home/software/t113-linux/out/gcc-linaro-5.3.1-2016.05-x86_64_arm-linux-gnueabi/bin
arm-linux-gnueabi-g++ -g -o test test.cpp

3.然后你就会看到一个test的可执行文件,把他拷贝到arm嵌入式设备中
4. 连接嵌入式设备 ,一般使用putty连接。使用串口线连接设备和电能,输入Serial line和 Speed进入arm系统。
5. 查看core dump机制是否打开

ulimit –c

如果是0则表示未打开,继续执行以下,即临时设备不限制文件大小

ulimit –c unlimited

6.查看core文件默认保存路径

cat /proc/sys/kernel/core_pattern

需要修改可以用以下命令

echo “/data/xxx/<core_file>” > /proc/sys/kernel/core_pattern

7.然后执行可执行文件,查看是否生成

8.当前手动执行,可以生成,但是如果是放在init.d中的启动脚本没有生成,就在启动脚本设置下core日志打开,路径设置以及对路径赋权,还有一些说法是切换了工作目录和用户,也可能导致不生成,可以再看。

具体实现步骤-qt代码中修改 core dump

1.在main.cpp中引入以下头文件

#include "signal.h"
#include <stdlib.h>
#include <sys/resource.h>

2.在main.cpp中添加以下方法

void create_core_dump() {
    struct rlimit coreDumpL;
    qDebug() << "create_core_dump  start";
       // 获取系统中设置的core文件的大小
       if (getrlimit(RLIMIT_CORE, &coreDumpL) == 0) {
           // 修改core文件大小
           coreDumpL.rlim_cur = RLIM_INFINITY;
           coreDumpL.rlim_max = RLIM_INFINITY;
           if (setrlimit(RLIMIT_CORE, &coreDumpL) != 0) {
                qDebug() << "Failed to set core dump size limit.";
           }
       }
       // 取消捕获SIGSEGV等信号
       signal(SIGSEGV, SIG_DFL);
       // 其他需要捕获的信号也可以设置为默认行为
         qDebug() << "create_core_dump  ending";
}

3.在main方法中加入以下

qInstallMsgHandler(customMessageHandler);//安装日志记录
create_core_dump(); // 调用生成core-dump

4.在.pro文件中添加以下

#release版程序带上调试信息
QMAKE_CC += -g
QMAKE_CXX += -g
QMAKE_LINK += -g
#release版程序带上调试信息

5.在qt的界面,即找到ui界面加入一个按钮,在按钮事件中写入一个空指针

 char* str = NULL;
    *str = 'a';

6.最后编译打包到arm上测试,就能看到生成了core文件

7.执行以下命令,就能看到堆栈信息

gdb 你的可执行文件 你的core日志

如有问题,可以联系shiyougue@qq.com

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐