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

时间:2018-08-26 10:07:04

标签: c windows debugging visual-studio-code gdb

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

现在,如果我的源文件的路径不包含任何空格,则可以正常工作。但是,如果它确实包含空格,则每当调试器尝试中断时,我都会收到以下消息: Unable to open 'Semester': File not found

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

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

我猜测是GDB向VS Code发送了指向文件的错误链接,或者VS Code无法理解文件路径中的空格(我对此表示怀疑)。抱歉,但是在调试会话期间,我不太了解GDB和VS Code之间的链接。

有人知道如何解决此问题吗?

tasks.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}
        }
    ]
}

launch.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"
        }
    ]
}

1 个答案:

答案 0 :(得分:0)

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

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


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

gcc -g -o target1.exe pathWithNoEmbeddedSpaces.c

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


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

gcc -g -o target2.exe path With Embedded Spaces.c

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


至于解决方案,引号就派上用场了,也称为引用。大多数 shell 可以同时使用单引号 (') 和双引号 (")。但您可能想查看外壳的详细信息。只要文件路径中有嵌入的空格,请使用引号。如:

gcc -g -o target2.exe "path With Embedded Spaces.c"

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


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

在 VS Code 的“远古时代”中,它只是简单地替换 JSON 文件中的预定义变量(例如 ${fileDirname}),然后连接以空格分隔的参数,并将命令传递给底层 shell。即使 VS Code 在涉及包含空格或其他特殊字符的命令和参数时执行特殊处理,它也不会检查预定义变量的替换。所以 ${fileBasename} 被替换而不加引号。

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

gcc -g -o test.exe test.c

编译应该没有任何问题,因为 test.c 位于当前工作目录中。但是,请考虑 launch.json 中的目标路径:

"program": "${fileDirname}\\${fileBasenameNoExtension}.exe"

由于没有引用,GDB会搜索名为E:\Libraries\Dropbox\UNI\Semester的程序,然后因为没有这样的程序而异常退出。


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

"-g", "-o", "'${fileBasenameNoExtension}.exe'", "'${fileBasename}'"
"-g", "-o", "\"${fileBasenameNoExtension}.exe\"", "\"${fileBasename}\""
"program": "'${fileDirname}\\${fileBasenameNoExtension}.exe'"

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