Files
VX5_KRO_GearPump/doc/VX5 Release编译发行.md
T
2026-07-02 14:32:38 +08:00

8.2 KiB

带崩溃转储功能的VX5 Release 编译发行、dump收集、问题分析

由于VX5相比VX4在稳定性上有些许差异,目前VX5在用户端仍然可能存在崩溃问题,作为兜底方案,我们引入了崩溃转储功能。 崩溃转储功能是工程化的软件项目中几乎必有的一个功能,它可以在软件崩溃时,将当前程序的函数调用栈、寄存器状态、内存状态等保存到dump上,开发人员依据dump文件结合程序日志可以快速定位到崩溃的位置。 带崩溃转储的发行版发布、dump收集、问题分析,步骤是:使用带-g编译标记编译release版本、生成带调试符号的可执行文件、分离调试符号生成符号调试表和不带调试符号的发行版可执行程序、将发行版可执行程序发布给用户上机运行、运行过程中触发崩溃、收集dump文件、将dump与之前分离的调试信息表以及发行版可执行程序放在一起,使用 addr2line 等工具封装为脚本将dump中的需要观察的调用栈地址、程序地址等转换为包含源码位置等的信息,最后进行源码分析并修复。

项目先决条件

在进行此方式编译发行前,可能需要检查以下先决条件,虽然这些已经在最新 VX5_V6.7.1 和 韩国VX5 项目中默认配置。

  1. QtUI.pro 中需包含如下配置:
CONFIG += qt warn_on debug_and_release  # 启用警告和调试信息
QMAKE_CXXFLAGS += -g                    # 启用 -g 编译标记
#QMAKE_POST_LINK += ulimit -c unlimited
LIBS += -ldl                      # 链接 dl 库,用于获取当前程序的基址

# ... 其他内容

# 包含 dump转储功能的头文件和源文件
HEADERS += dump.h
SOURCES += dump.cpp
  1. main.cpp 中需包含 dump.h 文件,并在 QApplication app 后第一时间调用 installSignalHandler() 函数,用于安装信号处理函数。
    QApplication a(argc, argv);
    gAppNameStr = QString::fromUtf8(argv[0]);
    installSignalHandlers();    // 这里安装信号处理函数
  1. dump.cpp dump.h 已添加至最新的标准VX5、韩国VX5项目中。
  2. 用于分离调试符号的脚本 strip_debug.sh 已添加至项目源码目录中。
  3. 用于分析dump文件的脚本 resolve_dump.sh 已添加至项目源码目录中。

编译发行

  1. 使用QtCreator IDE 一键release编译,或使用VScode 配置命令行,编译release版本的带调试符号的、满足项目需求的可执行文件,得到QtUI。
inkjet@ubuntu:/mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface$ ls ../arm_build/QtUI* -lh
-rwxrwxrwx 1 root root 55M 7月   1 10:22 ../arm_build/QtUI

可以看到QtUI的大小为55M,说明包含了调试符号,但是因为携带了调试符号,运行时可能会占用更多内存,且不利于用户发行更新,同时还包含了源码信息,存在泄漏风险。为此我们需要将调试符号分离出来,生成符号调试表和不带调试符号的发行版可执行程序。

  1. 使用之前编译QtUI时使用的交叉编译工具链中的 objcopy 工具,将QtUI的调试符号分离出来,对于 InkjetUbuntu-T1 虚拟机,已经包含了 objcopy 工具。

    使用命令行分离:进入QtUI所在目录,按如下命令进行操作:

inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ aarch64-linux-gnu-objcopy --only-keep-debug QtUI QtUI.dbg   # 分离调试符号生成符号调试表
inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ aarch64-linux-gnu-objcopy --strip-debug QtUI QtUI           # 移除调试符号
inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ aarch64-linux-gnu-objcopy --add-gnu-debuglink=QtUI.dbg QtUI # 关联调试符号文件和发行程序
inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ ls ./QtUI* -lh
-rwxrwxrwx 1 root root 6.7M 7月   1 10:43 ./QtUI
-rwxrwxrwx 1 root root  48M 7月   1 10:43 ./QtUI.dbg

注意输出结果,一个大小为6.7M的QtUI,该文件与平常不带-g编译出来的QtUI一致,用于用户发布;一个大小为48M的QtUI.dbg,存放调试符号信息,用于内部保留日后分析dump文件,两个文件进行了关联,因此两个文件在内部必须成对存放,不可缺一。

第二种方法:使用strip_debug.sh脚本分离调试符号 进入QtUI所在目录,按如下命令进行操作:

inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ ./strip_debug.sh
或者指定QtUI路径:
inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ ./strip_debug.sh QtUI

两种方式都可以生成QtUI和QtUI.dbg两个文件,此时将 QtUI 附上更新说明发布。将 QtUI.dbg QtUI 打包上传SVN仓库内部存放。

inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ ls ./QtUI_V6.7.1_韩国_2026年7月* -lh
-rwxrwxrwx 1 root root 23M 7月   1 11:11 ./QtUI_V6.7.1_韩国_2026年7月1日11_11_08.zip

注意明确标准编译时间,避免与用户端软件编译时间不一致导致的dump文件时间错误。 将携带QtUI.dbg的QtUI_V6.7.1_韩国_2026年7月1日11_11_08.zip上传至 https://pc-20181215fqqf/svn/src/QTUI软件版本/VX5 仓库。

然后仅将 QtUI与发行说明打包按正常流程发布。

收集dump文件

当用户端或产线测试发生崩溃,dump文件会被收集到/home/plg/loginfo目录下。

cat@lubancat:/home/plg/loginfo$ ls /home/plg/loginfo/dumpfile_2026_07_01_11_33_07.txt -lh
-rw-r--r-- 1 root root 3.1K  7月  1 11:33 /home/plg/loginfo/dumpfile_2026_07_01_11_33_07.txt

使用 QtUI 的日志导出功能,可将所有 dump 文件导出至U盘,dump 文件格式为 dumpfile_YYYY_MM_DD_HH_MM_SS.txt,按照崩溃时间记录。 拿到的dump文件可能如下

Stack trace info:
Base address: 0x557162e000

/home/plg/QtUI(+0x6b29c) [0x557169929c]
  ??:?

/home/plg/QtUI(+0x6b96c) [0x557169996c]
  ??:?

linux-vdso.so.1(__kernel_rt_sigreturn+0) [0x7f9d72458c]
  ??:0
...... 省略更多....

注意dump文件中缺失了源码信息,需要结合之前的QtUI.dbg文件进行分析。

分析dump文件

由于之前对编译好的QtUI进行了调试符号分离,因此崩溃捕获到的dump信息与普通不带-g编译的QtUI崩溃捕获的dump一样,会缺少调试符号。 因此我们将该dump文件与之前内部保存的 QtUI QtUI.dbg 放在一起,进行一点处理就可以获得完整的调试源码信息。 执行脚本resolve_dump.sh,即可获得完整的dump信息。

inkjet@ubuntu:/mnt/hgfs/share/bSpec/arm_build$ ./resolve_dump.sh ./dumpfile_2026_07_01_11_33_07.txt
Base address: 0x557162e000
QtUI 路径:    /mnt/hgfs/share/bSpec/arm_build/QtUI
QtUI.dbg:     /mnt/hgfs/share/bSpec/arm_build/QtUI.dbg
输出文件:     ./dumpfile_2026_07_01_11_33_07_resolved.txt

正在解析 dump 文件: ./dumpfile_2026_07_01_11_33_07.txt
=========================================

Stack trace info:

Base address: 0x557162e000


/home/plg/QtUI(+0x6b29c) [0x557169929c]
  createStackTraceFile(char const*, char const*) at /mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface/../arm_build/../800X600_New_SystemProject-_NewInterface/dump.cpp:54


/home/plg/QtUI(+0x6b96c) [0x557169996c]
  signalHandler(int) at /mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface/../arm_build/../800X600_New_SystemProject-_NewInterface/dump.cpp:96 (discriminator 9)


linux-vdso.so.1(__kernel_rt_sigreturn+0) [0x7f9d72458c]
  ??:0

/opt/Qt/lib/libQt5Widgets.so.5(_ZNK7QWidget11windowTitleEv+0xc) [0x7f9d1ad56c]
  ??:0

/home/plg/QtUI(+0x189f30) [0x55717b7f30]
  SetNumDlg::on_btn_confirm_clicked() at /mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface/../arm_build/../800X600_New_SystemProject-_NewInterface/setnumdlg.cpp:39


/home/plg/QtUI(+0x1b14d0) [0x55717df4d0]
  SetNumDlg::qt_metacall(QMetaObject::Call, int, void**) at /mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface/../arm_build/tmp/moc_setnumdlg.cpp:147

...... 省略更多....

注意输出结果

  SetNumDlg::on_btn_confirm_clicked() at /mnt/hgfs/share/bSpec/800X600_New_SystemProject-_NewInterface/../arm_build/../800X600_New_SystemProject-_NewInterface/setnumdlg.cpp:39

说明崩溃位于setnumdlg.cpp文件的39行。同时resolve_dump.sh脚本会生成dumpfile_2026_07_01_11_33_07_resolved.txt文件。