当源路径中有空格时,VS Code 调试失败

pro*_*ngo 5 c windows debugging gdb visual-studio-code

我正在尝试在 VS Code(Windows)中为我的 c 文件创建一个 GDB 调试管道。你可以在下面找到我的 tasks.json 和 launch.json。

现在,如果我的源文件的路径不包含任何空格,这可以正常工作。但是,如果它确实包含空格,则每当调试器尝试中断时,我都会收到这样的消息: 无法打开“学期”:找不到文件

这是因为它要查找的源文件实际上位于

E:\Libraries\Dropbox\UNI\Semester 5\test.c

而且我猜要么 GDB 向 VS Code 发送了一个指向该文件的错误链接,要么 VS Code 不理解其文件路径中的空格(我对此表示怀疑)。抱歉,我不太了解调试会话期间 GDB 和 VS Code 之间的联系。

有谁知道如何解决这一问题?

任务.json:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Build C Program",
            "type": "shell",
            "command": "gcc",
            "options": {"cwd": "${fileDirname}"},
            "args": [
                "-g", "-o", "${fileBasenameNoExtension}.exe", "${fileBasename}"
            ],
            "group": {"kind": "build","isDefault": true}
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

启动.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(gdb) Launch",
            "type": "cppdbg",
            "request": "launch",
            "program": "${fileDirname}\\${fileBasenameNoExtension}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${fileDirname}",
            "environment": [],
            "externalConsole": true,
            "MIMode": "gdb",
            "miDebuggerPath": "C:\\cygwin64\\bin\\gdb.exe",
            "setupCommands": [
                {
                    "description": "Enable pretty-printing for gdb",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ],
            "preLaunchTask": "Build C Program"
        }
    ]
}
Run Code Online (Sandbox Code Playgroud)

小智 2

我认为最新版本的 VS Code 可能已经解决了这个问题。但是,有关命令行参数如何工作的一些知识可能会帮助您了解此问题的原因。

基本上,shell 会分割由空格分隔的单词,并将这些单词视为独立的参数。对于路径中没有嵌入空格的文件,一切正常。对于路径中嵌入空格的文件,需要一些额外的输入来绕过这个陷阱。


假设我们要编译一个名为 的文件pathWithNoEmbeddedSpaces.c,我们只需输入:

gcc -g -o target1.exe pathWithNoEmbeddedSpaces.c
Run Code Online (Sandbox Code Playgroud)

在上述情况下,由空格分隔的命令行参数 from 、 togcc被视为独立参数。然后它们由 shell 传递给我们的编译器 GCC,它理解我们想要编译 1 个源文件。-gpathWithNoEmbeddedSpaces.c


假设我们要编译另一个名为 的文件path With Embedded Spaces.c,我们输入:

gcc -g -o target2.exe path With Embedded Spaces.c
Run Code Online (Sandbox Code Playgroud)

这次我们有多少独立的论点?8!现在,shell 将gcc...path With Embeded Spaces.c全部视为独立参数。GCC 很困惑,因为它看到的是编译 4 个源文件的要求,而这些文件甚至可能不存在于当前目录中!


至于解决方案,引号可以解决这个问题,也称为引用。大多数 shell 都可以使用单引号 ( ') 和双引号 ( ")。但您可能想检查您的 shell 的详细信息。只要文件路径中存在嵌入空格,就使用引号。例如:

gcc -g -o target2.exe "path With Embedded Spaces.c"
Run Code Online (Sandbox Code Playgroud)

shell 现在知道这path With Embedded Spaces.c是一个参数,应该将其视为一个整体,然后将其传递给 GCC 进行编译。


现在,VS Code 与这个问题有什么关系呢?

在 VS Code 的“远古时代”,它只是替换${fileDirname}JSON 文件中的预定义变量,然后连接以空格分隔的参数,并将命令传递到底层 shell。尽管 VS Code 在涉及包含空格或其他特殊字符的命令和参数时执行特殊处理,但它不会忽略预定义变量的替换。因此${fileBasename}无需报价即可被替换。

假设我们当前的工作目录是E:\Libraries\Dropbox\UNI\Semester 5,那么 VS Code 将替换${fileBasename}test.c${fileDirname}by E:\Libraries\Dropbox\UNI\Semester 5

gcc -g -o test.exe test.c
Run Code Online (Sandbox Code Playgroud)

编译应该不会出现任何问题,因为test.c位于当前工作目录中。但是,请考虑以下中的目标路径launch.json

"program": "${fileDirname}\\${fileBasenameNoExtension}.exe"
Run Code Online (Sandbox Code Playgroud)

由于没有使用引号, GDB 会搜索名为 name 的程序E:\Libraries\Dropbox\UNI\Semester,然后因不存在该程序而异常退出。


要处理包含嵌入空格的文件路径,请考虑使用引号。例如,您可以用单引号将预定义变量引起来:'${fileDirname}'、、'${fileBasename}'等。JSON 文件中的几行应类似于以下示例:

"-g", "-o", "'${fileBasenameNoExtension}.exe'", "'${fileBasename}'"
Run Code Online (Sandbox Code Playgroud)
"-g", "-o", "\"${fileBasenameNoExtension}.exe\"", "\"${fileBasename}\""
Run Code Online (Sandbox Code Playgroud)
"program": "'${fileDirname}\\${fileBasenameNoExtension}.exe'"
Run Code Online (Sandbox Code Playgroud)

但是,作为一般规则,请尽可能避免源文件路径中存在空格。