Linux 下如何在 VS Code 中启动 gdb 并加载 C++ 程序而不运行?
"launchCompleteCommand": "None" 会禁止调试器在初始化完成后自动运行程序。"stopAtEntry": true 控制的是程序运行后的暂停位置,不能让调试会话停留在“只加载文件、等待输入命令”的状态。VS Code 配置文档
现有日志只能说明 cppdbg 拒绝了当前状态下的求值请求,无法证明目标程序已经运行,也无法证明 stopAtEntry 失效。
如果需要在程序启动前设置环境,可以把脚本放进 setupCommands。如果需要手动完成“加载、执行脚本、设置参数、运行”的全过程,更适合在 VS Code 集成终端中使用原生 GDB。
为什么出现“进程正在运行”
使用 cppdbg 时,Debug Console 的输入会经过调试适配器。日志中的:
"command": "evaluate"
"context": "repl"
说明适配器将 show env PATH 作为一次调试协议求值请求处理。
在 MIEngine 的请求处理实现中,适配器会先检查会话是否处于暂停状态;如果没有,就返回错误码 1105。这一步发生在识别 -exec 命令之前,所以在当前状态下,即使改成:
-exec show environment PATH
也不一定能执行。
"launchCompleteCommand": "None" 跳过自动运行后,目标可能尚未启动,也没有产生让适配器进入暂停状态的停止事件。因此,报错中的“running”不能直接作为操作系统进程状态的证据,继续等待通常也无法改变这种状态。
方案一:启动前自动执行脚本,再运行到断点
如果只要求脚本先于程序执行,可以用 setupCommands 完成初始化,再正常启动程序。这种方式仍会运行程序,环境准备工作在运行前完成。
请将下面的路径和参数替换为实际值:
{
"version": "0.2.0",
"configurations": [
{
"name": "GDB with initialization script",
"type": "cppdbg",
"request": "launch",
"program": "/absolute/path/to/myprog-G",
"cwd": "/absolute/path/to/test-dir",
"MIMode": "gdb",
"miDebuggerPath": "/usr/bin/gdb",
"args": ["--config", "test.conf"],
"stopAtEntry": true,
"launchCompleteCommand": "exec-run",
"setupCommands": [
{
"description": "Enable pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"description": "Initialize program environment",
"text": "source /absolute/path/to/setup_env.py",
"ignoreFailures": false
}
]
}
]
}
setupCommands 用于初始化 GDB,args 指定目标程序的参数,exec-run 则在调试器配置完成后启动目标程序。各字段的含义见 VS Code 配置文档。
GDB 可以通过 source 执行 .py 脚本,前提是该 GDB 构建支持 Python,并启用了相应的脚本扩展识别。GDB Python 命令文档
环境初始化脚本应设置 "ignoreFailures": false,否则脚本失败后,程序仍可能在缺少环境配置的情况下启动。
如何明确停在 main
在 VS Code 的 Run and Debug 面板中找到 Breakpoints,选择 Add Function Breakpoint,输入:
main
然后使用正常的启动配置运行,即可通过函数断点明确指定在 main 处暂停。VS Code 函数断点文档
到达 main 时,动态加载器和部分 C++ 初始化代码可能已经执行。需要影响动态库加载的 LD_LIBRARY_PATH 必须在启动前设置,不能等停在 main 后再补。
方案二:在集成终端中完整保留手动流程
如果需要先看到 GDB 提示符,检查环境、执行脚本、设置参数,最后再决定何时运行,可以在 VS Code 集成终端中执行:
cd /absolute/path/to/test-dir
MYPROG_HOME=/opt/myprog /usr/bin/gdb -q /absolute/path/to/myprog-G
此时 GDB 已加载可执行文件,目标程序尚未运行。接着逐条输入:
show environment MYPROG_HOME
source /absolute/path/to/setup_env.py
show environment PATH
show environment LD_LIBRARY_PATH
set args --config test.conf
tbreak main
run
执行 run 才会创建并运行目标进程;tbreak main 会让程序在到达 main 时暂停一次。GDB 启动程序文档
这种方式保留了原生 GDB 的交互顺序,但该会话不会自动接入 VS Code 的变量、调用栈等调试面板。
注意 GDB 自身环境与目标程序环境的区别
Python 脚本使用:
os.environ["MYPROG_HOME"]
读取的是 GDB 进程自身的环境,因此需要在启动 GDB 前提供这个变量,上面的终端命令采用的就是这种方式。
GDB 命令:
set environment MYPROG_HOME = /opt/myprog
设置的是随后启动的目标程序的环境,不会同步修改 GDB 自身的 os.environ。launch.json 中的 environment 字段也用于配置目标程序环境,不能假定其中的变量会出现在 GDB Python 的 os.environ 中。
脚本要设置目标程序的环境,也应使用 GDB 的环境设置机制,例如:
import gdb
gdb.execute("set environment LD_LIBRARY_PATH = /opt/myprog/lib")
仅修改脚本中的 os.environ,不能保证目标程序收到预期值。可以用 show environment PATH 和 show environment LD_LIBRARY_PATH 检查 GDB 将传给程序的环境。GDB 环境变量文档
如何继续排查
可以在对应的调试配置对象中保留日志配置:
"logging": {
"engineLogging": true,
"trace": true,
"traceResponse": true
}
查看从启动到报错的完整日志,重点检查:
- 是否通过
-file-exec-and-symbols成功加载了指定文件。 - 是否发送过
-exec-run,或有脚本执行了run、start。 - 是否收到
*running、*stopped等 GDB/MI 通知。 - 初始化脚本是否返回错误,以及适配器是否向 VS Code 报告了停止事件。
如果目标已经启动,可以尝试工具栏的暂停按钮;如果尚未启动,暂停按钮未必能产生所需的停止事件。
进入正常暂停状态后,在 Debug Console 中执行 GDB 命令需要加上 -exec:
-exec show environment PATH
-exec show environment LD_LIBRARY_PATH
这是 C/C++ 扩展提供的命令入口,仍需通过前述状态检查。[VS Code 调试命令文档](https://code.visualstudio.com/docs/cpp/cpp-debug#_gdb-lldb-and-lldbmi-commands-gdbll db)
现有日志不足以将问题归因于 GDB 14.2。可以先用同一个 GDB 路径在终端中验证脚本,再对比正常启动配置与 "None" 配置的完整日志,以便确定问题出在脚本、GDB 启动过程,还是调试适配器的状态处理上。
备注:内容仅供参考。
