PAYATHON 2026

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 启动过程,还是调试适配器的状态处理上。

备注:内容仅供参考。