医疗健康图像处理数据可视化桌面应用3D渲染【免费下载链接】SlicerMulti-platform, free open source software for visualization and image computing.项目地址https://gitcode.com/gh_mirrors/sl/Slicer点击查看免费下载本文基于 Slicer 官方文档Docs/developer_guide/debugging/linuxcpp.md系统讲解在 GNU/Linux 上调试 Slicer C 代码的四种 GDB 工作流附加运行中进程、通过执行器启动参数、跟随 fork 子进程、exec-wrapper 包装脚本以及崩溃 core 文件的获取与分析方法。读完后你将能够绕过 Slicer 双层可执行结构Slicer启动器 SlicerApp-real真实进程带来的调试障碍独立完成断点调试与 segfault 回溯并可进一步衔接 Qt Creator、VS Code 等跨平台 IDE 调试方案。为什么 Linux 下调试 Slicer 比常规 Qt 项目麻烦Slicer 在 Linux 上并不是一个可执行文件的结构。从构建系统 CMake/SlicerMacroBuildApplication.cmake 可以看到在非 Apple 平台上真实的应用二进制会被命名为应用名App-realset(executable_name ${SLICERAPP_APPLICATION_NAME}) if(NOT APPLE) set(executable_name ${executable_name}App-real) endif()即最终产生两个可执行文件Slicer由 CTKAppLauncher 生成的启动器launcher负责设置LD_LIBRARY_PATH、PATH、PYTHONPATH等环境变量后 fork/exec 出真实进程SlicerApp-real真正运行的应用程序包含全部符号断点必须打在这里。这就是本文所有调试技巧的共同出发点要么在SlicerApp-real运行时把它 attach 进 GDB要么设法让 GDB 越过启动器直接调试真实进程。方法一GDB 附加到运行中进程推荐文档将 attach 方式列为推荐方案流程分四步。1. 解除 yama ptrace 限制自 Ubuntu 10.10 起内核的 yama LSM 默认禁止普通用户 ptrace 非子进程只有父进程才能附加到自己的子进程。临时放开$ echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope永久放开则编辑/etc/sysctl.d/10-ptrace.conf将kernel.yama.ptrace_scope 1改为kernel.yama.ptrace_scope 02. 用--attach-process拿到 PID$ ./Slicer --attach-process该参数会在加载任何模块之前弹出一个显示当前进程PID的消息框因此既方便 attach也适合调试模块加载阶段就发生的崩溃。这个行为可以在源码中确认Base/QTCore/qSlicerCoreApplication.cxx 中应用初始化环境时检查该参数并弹出提示// allow a debugger to be attached during startup if (qApp-arguments().contains(--attach-process)) { // Message for developers - do not translate. QString msg(/*no tr*/ This message box is here to give you time to attach your debugger to process [PID %1]); QMessageBox::information(nullptr, /*no tr*/ Attach process, msg.arg(QCoreApplication::applicationPid())); }如果不使用该参数也可以直接查询进程$ ps -Afww | grep SlicerApp-real3. 附加进程并继续执行$ gdb --pid $PIDABOVE进入 GDB 后执行(gdb) continue让被暂停的进程恢复运行此时即可正常下断点。小技巧在 GDB 中打印QString需要借助 Qt 提供的调试辅助函数可参考文档给出的 printQString 资料文档原文指向 silmor.de 的printqstring页面属于 Qt 通用技巧。方法二利用执行器的启动参数Slicer 的执行器app launcher本身就提供了携带 Slicer 环境启动其他程序的能力这是 CTKAppLauncher 的通用特性在 CMake/SlicerMacroBuildApplication.cmake 中通过ctkAppLauncherAppendExtraAppToLaunchToList逐个注册附加可执行程序例如构建树上自动注册--gnome-terminal、--xterm、--designer等选项。与调试相关的两个选项--launch executable [parameters]执行任意程序且程序继承 Slicer 的完整环境变量。例如Slicer --launch /usr/bin/gnome-terminal启动一个 gnome-terminal随后即可在该终端里直接对SlicerApp-real运行 GDB--gdb直接启动 GDB并在调试器环境内执行SlicerApp-real。方法三让 GDB 跟随 fork 出的子进程既然Slicer只是启动器可以直接对启动器下 GDB再让 GDB 切换到 fork 出来的SlicerApp-realgdb SlicerGDB 会提示Slicer没有调试符号——这是正常的因为它只是 launcher。接着设置跟随模式并运行(gdb) set follow-fork-mode child (gdb) runGDB 启动Slicer后会自动 attach 到 fork 出的SlicerApp-real之后即可正常调试。方法四使用 exec-wrapper 直接调试适合 IDE 集成exec-wrapper 方案用一个包装脚本模拟 app launcher 的环境变量行为使 GDB 或任何控制 GDB 的程序如 IDE可以在不 attach的情况下交互式调试。包装脚本的核心思想与 CMake/SlicerBlockCTKAppLauncherSettings.cmake 中定义的 launcher 设置一一对应该 CMake 文件分构建树 / 安装树两组维护SLICER_LIBRARY_PATHS、SLICER_PATHS、SLICER_ENVVARS等变量最终生成SlicerLauncherSettings.ini[LibraryPaths]的内容进入LD_LIBRARY_PATH[Paths]的内容进入PATH[EnvironmentVariables]中的每一项逐一设置如SLICER_HOME、PYTHONHOME、PYTHONPATH、QT_PLUGIN_PATH等。然后启动 GDB(gdb) set exec-wrapper ./WrapSlicer (gdb) exec-file ./bin/SlicerQT-real (gdb) runSlicerQT-real为文档撰写时期的进程名对应现版本的SlicerApp-real。关闭线程事件噪声由于 VTK 和 ITK 包含大量多线程过滤器渲染和处理期间 GDB 默认会刷屏输出类似[New Thread 0x7fff8378f700 (LWP 20510)] [Thread 0x7fff8b0aa700 (LWP 20506) exited]用以下命令关闭set print thread-events off生成 wrapper 脚本的实用技巧最简单的方式是让 launcher 自己示范环境变量。执行Slicer --launch which gnome-terminal或Slicer --gnome-terminal然后在弹出的终端中查看LD_LIBRARY_PATH的取值注意文档提醒通过--xterm启动时该变量似乎不会被设置再对照[EnvironmentVariables]检查其余变量。文档附了一份当时的SlicerLauncherSettings.ini完整示例展示了 launcher 配置的五个主要区块[General]、[Application]、[ExtraApplicationToLaunch]、[LibraryPaths]、[Paths]、[EnvironmentVariables]。关键部分摘录如下完整文件见 Docs/developer_guide/debugging/linuxcpp.md[General] launcherSplashImagePath... launcherSplashScreenHideDelayMs3000 additionalLauncherHelpShortArgument-h additionalLauncherHelpLongArgument--help additionalLauncherNoSplashArguments--no-splash,--help,--version,--home,--program-path,--no-main-window [Application] pathAPPLAUNCHER_DIR/bin/./SlicerQT-real arguments [ExtraApplicationToLaunch] gnome-terminal/shortArgument gnome-terminal/helpStart gnome-terminal gnome-terminal/path/usr/bin/gnome-terminal gnome-terminal/arguments gdb/shortArgument gdb/helpStart gdb gdb/path/usr/bin/gdb gdb/arguments [LibraryPaths] 1\path... 8\pathAPPLAUNCHER_DIR/bin/. 9\path../lib/Slicer-4.0/qt-loadable-modules ... size18 [Paths] 1\pathAPPLAUNCHER_DIR/bin/. ... size5 [EnvironmentVariables] QT_PLUGIN_PATHAPPLAUNCHER_DIR/binPATHSEP... SLICER_HOME... PYTHONHOME... PYTHONPATH... TCL_LIBRARY... TK_LIBRARY... TCLLIBPATH...其中APPLAUNCHER_DIR、PATHSEP是 CTKAppLauncher 的占位符分别在运行时被替换为启动器所在目录与平台路径分隔符。当前仓库中这些路径并非手维护而是由 CMake/SlicerBlockCTKAppLauncherSettings.cmake 程序化生成——例如构建树的SLICER_LIBRARY_PATHS_BUILD、SLICER_PATHS_BUILD、SLICER_PYTHONPATH_BUILD以及安装树对应的*_INSTALLED变量——阅读该文件即可理解任何一次生成的SlicerLauncherSettings.ini的来龙去脉。如果--launch方式不可用上述 ini 设置可以直接翻译为如下 bash 包装脚本#!/bin/bash BASE_DIR/cmn/git/Slicer4-sb/ APPLAUNCHER_DIR$BASE_DIR/Slicer-build LD_PATHS /cmn/git/Slicer4-sb/VTK-build/bin/. /cmn/git/Slicer4-sb/CTK-build/CTK-build/bin/. /usr/lib /cmn/git/Slicer4-sb/ITKv3-build/bin/. /cmn/git/Slicer4-sb/SlicerExecutionModel-build/ModuleDescriptionParser/bin/. /cmn/git/Slicer4-sb/teem-build/bin/. /cmn/git/Slicer4-sb/LibArchive-install/lib $APPLAUNCHER_DIR/bin/. ../lib/Slicer-4.0/qt-loadable-modules $APPLAUNCHER_DIR/lib/Slicer-4.0/cli-modules/. $APPLAUNCHER_DIR/lib/Slicer-4.0/qt-loadable-modules/. /cmn/git/Slicer4-sb/tcl-build/lib /cmn/git/Slicer4-sb/OpenIGTLink-build /cmn/git/Slicer4-sb/OpenIGTLink-build/bin/. /cmn/git/Slicer4-sb/CTK-build/PythonQt-build/. /cmn/git/Slicer4-sb/python-build/lib /cmn/git/Slicer4-sb/python-build/lib/python2.6/site-packages/numpy/core /cmn/git/Slicer4-sb/python-build/lib/python2.6/site-packages/numpy/lib for STR in $LD_PATHS; do LD_LIBRARY_PATH${STR}:${LD_LIBRARY_PATH}; done QT_PLUGIN_PATH$APPLAUNCHER_DIR/bin:/cmn/git/Slicer4-sb/CTK-build/CTK-build/bin:/usr/lib/qt4/plugins SLICER_HOME/cmn/git/Slicer4-sb/Slicer-build PYTHONHOME/cmn/git/Slicer4-sb/python-build PYTHONPATH$APPLAUNCHER_DIR:/bin:$APPLAUNCHER_DIR:/bin/Python:/cmn/git/Slicer4-sb/python-build/lib/python2.6/site-packages:$APPLAUNCHER_DIR/lib/Slicer-4.0/qt-loadable-modules/.:$APPLAUNCHER_DIR/lib/Slicer-4.0/qt-loadable-modules/Python TCL_LIBRARY/cmn/git/Slicer4-sb/tcl-build/lib/tcl8.4 TK_LIBRARY/cmn/git/Slicer4-sb/tcl-build/lib/tk8.4 TCLLIBPATH/cmn/git/Slicer4-sb/tcl-build/lib/itcl3.2:/cmn/git/Slicer4-sb/tcl-build/lib/itk3.2 export QTPLUGIN_PATH$QT_PLUGIN_PATH export SLICER_HOME$SLICER_HOME export PYTHONHOME$PYTHONHOME export PYTHONPATH$PYTHONPATH export TCL_LIBRARY$TCL_LIBRARY export TK_LIBRARY$TK_LIBRARY export TCLLIBPATH$TCLLIBPATH export LD_LIBRARY_PATH$LD_LIBRARY_PATH exec $脚本末尾的exec $是关键GDB 的exec-wrapper机制会用脚本 被调试程序作为命令执行真实进程成为脚本的子进程exec保证 GDB attach 到的就是它本身。分析段错误Segmentation Fault在构建树中复现并加载 core$ ulimit -c unlimited $ ./Slicer ... make it crash $ ./Slicer --gdb ./bin/SlicerApp-real (gdb) core core (gdb) backtrace ...在已安装的 Slicer 中$ ulimit -c unlimited $ ./Slicer ... make it crash $ ./Slicer --launch bash $ gdb ./bin/SlicerApp-real (gdb) core core (gdb) backtrace ...已安装版本用--launch bash开一个继承 Slicer 环境的 shell再在其中启动 GDB 加载SlicerApp-real对应的 core 文件。注意GDB 自身依赖 Python而 GDB 链接的 Python 与 Slicer 自带的 Python 并非同一套可能造成启动问题。若 GDB 因缺少_sysconfigdata__linux_x86_64-linux-gnu.py而无法启动需要把 Slicer 的 sysconfigdata 文件复制为期望的文件名例如cd ~/Slicer-4.13.0-2021-09-10-linux-amd64/lib/Python/lib/python3.6 cp _sysconfigdata_m_linux2_.py _sysconfigdata__linux_x86_64-linux-gnu.pysystemd 系统上的 coredump 处理在启用 systemd 的发行版中coredump 由 systemd 的 coredump 守护进程接管以.lz4压缩格式存储在/var/lib/systemd/coredump/core.SlicerApp-real.xxxx.lz4即使设置了ulimit -c unlimitedcoredump 仍可能被截断truncated。用coredumpctl list查看最近的 coredump 及对应 PIDcoredumpctl list Thu 2018-05-24 16:37:46 EDT 22544 1000 1000 11 missing /usr/lib/firefox/firefox Fri 2018-05-25 15:50:52 EDT 14721 1000 1000 6 truncated /path/Slicer-build/bin/SlicerApp-real Mon 2018-05-28 11:35:43 EDT 17249 1000 1000 6 present /path/Slicer-build/bin/SlicerApp-real若状态为truncated可修改/etc/systemd/coredump.conf提高默认最大文件尺寸[Coredump] #Storageexternal #Compressyes ProcessSizeMax8G ExternalSizeMax8G JournalSizeMax6G #MaxUse #KeepFree修改后再次触发崩溃core 文件状态应变为present。随后用coredumpctl直接拉起 GDB不带 PID 时默认使用最新一个 coredumpcoredumpctl gdb $PID若要在其他 IDE 或 ddd 中使用需先解压 coredump可通过修改coredump.conf的Compress选项或直接导出coredumpctl dump $PID /tmp/corefile进一步跨平台 IDE 调试文档最后指出上述 GDB 工作流可与 IDE 集成仓库中对应有三篇姊妹篇文档可继续深入Debugging using CodeLiteDebugging using Qt CreatorDebugging using Visual Studio Code其中 Qt Creator 篇给出了典型做法先用./Slicer --launch /path/to/qtcreator启动 IDE 以继承 Slicer 环境这正是前文--launch选项的应用再打开CMakeLists.txt选择 Slicer-build 目录进行构建配置。总结四种方式的选择依据| 场景 | 推荐方式 | | | | | 快速对运行中的 Slicer 下断点 |--attach-processgdb --pid需先放开 yama ptrace_scope | | 需要带 Slicer 环境的手动调试 |Slicer --gdb或Slicer --launch bash| | 不想预先启动 Slicer让 GDB 全程托管 |set follow-fork-mode child跟随 fork | | IDE 集成、需要完整控制 GDB 生命周期 | exec-wrapper 包装脚本 | | 程序已崩溃只剩 core 文件 |ulimit -c unlimited复现 core/backtracesystemd 系统改用coredumpctl|所有流程的共同前提是要清楚Slicerlauncher与SlicerApp-real真实进程的分工断点、符号、core 分析都必须针对后者进行而 launcher 的价值在于替你准备好一整套可复现的调试环境。赞分享医疗健康图像处理数据可视化桌面应用3D渲染【免费下载链接】SlicerMulti-platform, free open source software for visualization and image computing.项目地址https://gitcode.com/gh_mirrors/sl/Slicer点击查看免费下载相关推荐Ceph 开发环境 GDB 调试指南附加运行进程与 Teuthology 故障分析Ceph 开发环境 GDB 调试指南附加运行进程与 Teuthology 故障分析 GDBGNU Project Debugger是分析进程执行流程、定位存储分布式文件系统对象存储后端高可用tflite-micro 在 QEMU 上运行 Cortex-M 单元测试环境搭建、测试执行与 GDB 调试实战指南tflite micro 在 QEMU 上运行 Cortex M 单元测试环境搭建、测试执行与 GDB 调试实战指南 本篇技术指南以 qemu.md http人工智能深度学习推理引擎本地部署嵌入式物联网UE4SS C Mod 调试实战使用 await_debugger 附加调试器逐行排查UE4SS C Mod 调试实战使用 await_debugger 附加调试器逐行排查 本文面向 UE4SS C Mod 开发者当日志输出不足以定位游戏开发逆向工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考