VS Code C++ 调试报错:preLaunchTask exit code -1 的排查与解决#
今天在 VS Code 里写洛谷 P1126《机器人搬重物》,代码写完之后准备按 F5 调试,结果还没开始调试,VS Code 先给我弹了一个错误:
1
| The preLaunchTask 'C/C++: g++.exe build active file' terminated with exit code -1.
|
一开始我第一反应就是:
是不是代码又写崩了?
毕竟 P1126 本身就是 BFS,边界、数组、方向这些地方稍微写错一点,就很容易出问题。
但不对啊,我数据还没输呢,用hello world试了一下报同样的错。
整个过程比较曲折,中间还碰到了 chcp、tasks.json、launch.json、g++、gdb、VS Code 扩展等一堆东西。这里把整个过程记录下来,之后如果再碰到类似问题,也可以直接回来查。
一、刚开始的报错#
按下 F5 后,VS Code 弹出:

1
| The preLaunchTask 'C/C++: g++.exe build active file' terminated with exit code -1.
|
然后终端里面还有:
1
2
3
4
5
| cmd /c chcp 65001>nul && D:\mingw64\bin\g++.exe -fdiagnostics-color=always -g D:\code_world\code_cpp\hello.cpp -o D:\code_world\code_cpp\hello.exe
'chcp' 不是内部或外部命令,也不是可运行的程序
Build finished with error(s).
The terminal process failed to launch (exit code: -1).
|
最引人注意的就是:
问题来了。
chcp 是 Windows 自带的命令,我直接打开 Windows 的 cmd 测试:
完全正常。
这就有点奇怪了:
1
2
3
4
5
6
7
| Windows cmd
↓
chcp 正常
VS Code
↓
chcp 找不到
|
所以当时我就开始怀疑是 VS Code 的环境有问题。
二、先看看 g++ 和 gdb 有没有问题#
既然怀疑环境,最简单的方法就是直接测试编译器。
在 VS Code 终端输入:
输出:
1
| g++.exe (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0
|
再测试 gdb:
输出:
这说明至少有两个东西是正常的:
都能被找到。
所以暂时不用考虑重新安装 MinGW。
三、检查 tasks.json#
接下来检查 .vscode/tasks.json。
我的配置大概是这样:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| {
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "D:\\mingw64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
},
"detail": "Task generated by Debugger."
}
],
"version": "2.0.0"
}
|
看了一遍,没有发现什么明显问题。
尤其是:
1
| "command": "D:\\mingw64\\bin\\g++.exe"
|
这里直接写的是 g++ 的绝对路径。
也就是说,即使 PATH 有问题,VS Code 也应该能够直接找到这个 g++。
所以:
tasks.json 暂时排除。
四、然后发现一个关键问题:没有 launch.json#
继续检查 .vscode 文件夹,发现之前其实没有配置 launch.json。
这时候才意识到,我对 VS Code 的“编译”和“调试”其实一直没有完全搞清楚。
简单来说:
tasks.json 干什么?#
负责:
比如:
1
2
3
| 调用 g++.exe
输入哪个 cpp
输出哪个 exe
|
launch.json 干什么?#
负责:
比如:
1
2
3
| 启动哪个 exe
使用哪个 gdb
程序运行时的工作目录是什么
|
而 preLaunchTask 就是把两者连接起来。
可以简单理解成:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| F5
↓
launch.json
↓
preLaunchTask
↓
tasks.json
↓
g++
↓
生成 exe
↓
gdb
↓
开始调试
|
所以我补了一个 launch.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| {
"version": "0.2.0",
"configurations": [
{
"name": "C/C++: g++.exe 调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "D:\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++.exe build active file"
}
]
}
|
这里有一行特别重要:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
它必须和 tasks.json 里的:
1
| "label": "C/C++: g++.exe build active file"
|
完全一致。
五、结果加了 launch.json 还是报错#
本来以为这下应该好了。
结果按 F5:
1
| The preLaunchTask 'C/C++: g++.exe build active file' terminated with exit code -1.
|
还是这个。
然后终端里依旧有:
1
| cmd /c chcp 65001>nul && D:\mingw64\bin\g++.exe ...
|
紧接着:
1
| 'chcp' 不是内部或外部命令,也不是可运行的程序
|
这时候我基本确定:
这次的问题应该不是 C++ 代码,而是 VS Code 执行任务时的 shell 环境。
六、为什么 VS Code 会执行 chcp?#
这里顺便查了一下 chcp。
chcp 是 Windows cmd 的一个命令,用来切换控制台代码页。
例如:
就是切换到 UTF-8。
VS Code 的 C++ 构建任务在 Windows 下可能会生成类似这样的命令:
1
| cmd /c chcp 65001>nul && g++ ...
|
也就是说:
1
2
3
| 先执行 chcp 65001
↓
再执行 g++
|
所以如果 chcp 出问题,VS Code 就可能把整个任务判定成失败。
问题也就变成了:
为什么 Windows 自己的 cmd 能执行 chcp,VS Code 里面却找不到?
七、开始检查 VS Code 的终端配置#
当时我的 settings.json 里面配置了多个终端:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| "terminal.integrated.profiles.windows": {
"PowerShell": {
"source": "PowerShell",
"icon": "terminal-powershell"
},
"Command Prompt": {
"path": "C:\\WINDOWS\\System32\\cmd.exe",
"args": [
"/K",
"chcp 65001"
]
},
"Git Bash": {
"source": "Git Bash",
"icon": "terminal-git-bash"
},
"PowerShell 7": {
"path": "pwsh.exe",
"icon": "terminal-powershell"
}
},
"terminal.integrated.defaultProfile.windows": "PowerShell 7"
|
这里确实有点复杂。
我配置了:
- PowerShell
- PowerShell 7
- Command Prompt
- Git Bash
而且 Command Prompt 自己又加了:
这就让我开始怀疑,是不是终端配置之间发生了冲突。
于是我把默认终端改成:
1
| "terminal.integrated.defaultProfile.windows": "Command Prompt"
|
结果……
还是不行。
chcp 依然报错。
八、又尝试绕开 cppbuild#
既然问题可能出在 VS Code 自动生成的:
1
| cmd /c chcp 65001>nul && ...
|
那我就想:
能不能不让它自动生成?
于是尝试把:
改成:
希望直接按照自己的命令执行。
结果还是一样。
后来还尝试过:
1
| "terminal.integrated.inheritEnv": false
|
想让 VS Code 不继承主进程的环境变量。
但也没有解决。
这时候就有点尴尬了。
因为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| 系统 cmd
↓
chcp 正常
VS Code
↓
chcp 不正常
g++
↓
正常
gdb
↓
正常
|
问题越来越像 VS Code 自己的环境了。
九、检查 VS Code 日志,又发现了一些奇怪东西#
继续看 VS Code 的日志,发现里面有:
1
| Failed to find the "go" binary in either GOROOT() or PATH
|
同时看到 VS Code 加载了大量扩展:
1
2
3
4
5
6
7
8
9
| anthropic.claude-code
golang.go
ms-azuretools.vscode-containers
ms-dotnettools.csdevkit
ms-python.python
redhat.java
vscjava.vscode-gradle
xsro.masm-tasm
...
|
也就是说,这个 VS Code 并不是一个单纯的 C++ 开发环境。
Go、Java、Python、C#、Docker、Gradle、汇编等一大堆扩展都装了。
所以当时一个比较自然的猜测就是:
会不会某个扩展在启动的时候修改了 PATH?
这个方向确实值得怀疑。
不过后来回头看,这里最好不要直接下结论说“这些扩展一定污染了 PATH”。
因为仅仅看到扩展加载,并不能证明某一个扩展就是罪魁祸首。
更准确的说法应该是:
VS Code 内部的环境变量和 shell 配置与系统 cmd 存在差异,而扩展和 VS Code 配置都属于需要排查的对象。
十、最关键的一次测试:程序居然真的运行了#
后来为了彻底搞清楚到底有没有编译成功,我没有再看 VS Code 弹窗,而是直接手动执行调试器。
类似:
1
| D:\code_world\code_cpp> cmd /C "...WindowsDebugLauncher.exe ... --dbgExe=D:\mingw64\bin\gdb.exe --interpreter=mi "
|
结果程序正常输出:
这一下就很有意思了。
因为这说明:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| g++
↓
编译成功
gdb
↓
启动成功
exe
↓
存在
程序
↓
正常运行
|
也就是说,之前看到的:
并不能简单理解为:
“C++ 编译失败了。”
至少在这次环境里,实际的编译和调试流程是可以跑起来的。
所以之前那个错误更像是:
VS Code 的任务系统因为 shell 环境中的 chcp 异常,把整个 preLaunchTask 判定成了失败。
这也是为什么我后来把它称为“干扰性报错”。
十一、真正把问题搞清楚,是因为我删了一行配置#
后来排查的时候,我为了测试,直接把:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
删掉了。
然后再按 F5。
这次 VS Code 给出了一个完全不同的错误:
1
| launch: program 'D:\code_world\code_cpp\luogu\P1126.exe' does not exist
|
这次就很好理解了。
因为没有 preLaunchTask:
1
2
3
4
5
6
7
8
9
| F5
↓
不编译
↓
直接找 P1126.exe
↓
文件不存在
↓
报错
|
这也从侧面证明了:
preLaunchTask 确实是 F5 自动编译流程中的关键配置。
把它恢复:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
整个流程就恢复了。
十二、所以最终到底是什么问题?#
现在回头看,整个问题其实是两个事情叠在了一起。
问题一:launch.json 的 preLaunchTask#
这个是真正影响 F5 自动编译流程的关键配置。
如果没有:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
那么 F5 不会自动执行:
而是直接尝试启动:
指定的 exe。
如果 exe 还没有生成,就会看到:
1
| program ... does not exist
|
问题二:chcp 报错#
另外还有一个:
它来自 VS Code 执行构建任务时的 shell 环境。
这部分容易把人带偏,因为它看起来特别像:
但实际测试发现:
都是可以工作的。
所以这部分更像是 VS Code 任务系统中的环境问题,而不是 C++ 程序本身的问题。
十三、最后的配置#
如果只是想让 VS Code 正常完成:
可以使用下面这套配置。
tasks.json#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| {
"version": "2.0.0",
"tasks": [
{
"type": "cppbuild",
"label": "C/C++: g++.exe build active file",
"command": "D:\\mingw64\\bin\\g++.exe",
"args": [
"-fdiagnostics-color=always",
"-g",
"${file}",
"-o",
"${fileDirname}\\${fileBasenameNoExtension}.exe"
],
"options": {
"cwd": "${fileDirname}"
},
"problemMatcher": [
"$gcc"
],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
|
launch.json#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| {
"version": "0.2.0",
"configurations": [
{
"name": "C/C++: g++.exe 调试活动文件",
"type": "cppdbg",
"request": "launch",
"program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${fileDirname}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"miDebuggerPath": "D:\\mingw64\\bin\\gdb.exe",
"setupCommands": [
{
"description": "为 gdb 启用整齐打印",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "C/C++: g++.exe build active file"
}
]
}
|
终端部分可以先保持简单:
1
2
3
4
5
6
| "terminal.integrated.profiles.windows": {
"Command Prompt": {
"path": "C:\\Windows\\System32\\cmd.exe"
}
},
"terminal.integrated.defaultProfile.windows": "Command Prompt"
|
十四、以后遇到类似问题,可以这样查#
如果以后 VS Code 又出现:
1
| preLaunchTask ... exit code -1
|
不要第一时间去改 C++ 代码。
可以按照这个顺序检查。
第一步:直接编译#
在终端执行:
1
| g++ test.cpp -o test.exe
|
如果能生成:
说明 g++ 基本没问题。
第二步:直接运行#
如果程序正常运行,说明:
至少基本正常。
第三步:检查 gdb#
确认调试器是否存在。
第四步:检查 tasks.json#
重点看:
1
| "command": "D:\\mingw64\\bin\\g++.exe"
|
以及:
1
| "label": "C/C++: g++.exe build active file"
|
第五步:检查 launch.json#
重点看:
1
| "program": "${fileDirname}\\${fileBasenameNoExtension}.exe"
|
以及:
1
| "miDebuggerPath": "D:\\mingw64\\bin\\gdb.exe"
|
最重要的是:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
第六步:确认两个名字完全一样#
这两个地方:
1
2
| // tasks.json
"label": "C/C++: g++.exe build active file"
|
和:
1
2
| // launch.json
"preLaunchTask": "C/C++: g++.exe build active file"
|
必须一模一样。
哪怕少一个字符,F5 都无法正确找到对应的编译任务。
十五、这次踩坑最大的收获#
这次问题让我比较深的一个感受就是:
VS Code 的报错信息不一定就是最终原因。
比如这次看到:
1
| preLaunchTask ... exit code -1
|
很容易直接理解成:
但实际上继续往下看才发现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| chcp
↓
shell 环境异常
g++
↓
其实可以工作
gdb
↓
其实也可以工作
exe
↓
实际上能够运行
|
所以以后看到类似错误,最好不要只盯着第一行红色报错。
把终端完整输出往下看,经常能发现真正有用的信息。
最后总结一下#
这次的问题可以简单概括成:
1
2
3
4
5
6
7
| F5
↓
VS Code 执行 preLaunchTask
↓
任务环境出现 chcp 异常
↓
VS Code 报 exit code -1
|
同时,如果:
里面没有:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
那么 F5 又不会自动编译程序,就会进一步出现:
1
| program xxx.exe does not exist
|
所以最终需要保证的核心配置就是:
1
| "preLaunchTask": "C/C++: g++.exe build active file"
|
让整个流程重新变成:
1
2
3
4
5
6
7
8
9
10
11
| 按 F5
↓
执行 tasks.json
↓
g++ 编译
↓
生成 exe
↓
启动 gdb
↓
进入调试
|
至于 chcp 的问题,如果后面还频繁出现,可以再单独排查 VS Code 的 PATH、终端 profile 和扩展环境。
不要因为一个 exit code -1 就马上重装 MinGW,也不要一上来就怀疑自己。先把“代码、编译、调试、VS Code 任务、终端环境”一层一层拆开,定位起来会快很多。