vs code中编写c++基本使用以及问题总结

vs code基本使用以及总结

launch.json作用

这个文件配置了调试器的设置,允许你定义如何启动和调试你的程序。这包括配置执行路径、传递给程序的参数、环境变量以及特定语言或框架的调试器选项。

常用配置

  • "version": "0.2.0": 这是配置文件格式的版本号,通知 VS Code 使用特定的解析方式。
  • "configurations": [...]: 这个数组包含了一系列的调试配置,每个配置项允许您以不同的方式启动和调试程序。

对于数组中的单个配置对象:

  • "name": "(gdb) 启动": 这是调试配置的名称,您会在启动调试会话时在 VS Code 的调试菜单中看到它。
  • "type": "cppdbg": 指定调试器类型,cppdbg 是 C/C++ 的调试器。
  • "request": "launch": 表示这是一个启动(而不是附加)调试会话的请求。
  • "program": "${workspaceFolder}/a.exe": 指定了要调试的程序的路径。${workspaceFolder} 是一个变量,指的是您的工作区目录。
  • "args": []: 为程序指定命令行参数的数组,这里为空,意味着不传递任何参数。
  • "stopAtEntry": false: 指定调试器是否在程序入口点停止,这里设置为 false,表示不在入口点停止。
  • "cwd": "${workspaceFolder}": 设置程序的当前工作目录,这里也使用了**${workspaceFolder}**变量。
  • "environment": []: 允许您指定环境变量的数组,这里为空,意味着使用默认环境。
  • "externalConsole": false: 指定是否为调试的程序使用外部控制台窗口。设置为**false**表示不使用外部控制台。
  • "MIMode": "gdb": 指定使用的调试器接口,这里是 GDB(GNU调试器)。
  • "miDebuggerPath": "D:\\Program Files (x86)\\msys64\\mingw64\\bin\\gdb.exe": 提供 GDB 调试器可执行文件的路径。
  • "setupCommands": [...]: 包含一组在调试会话开始时自动执行的 GDB 命令。
    • "description": 提供命令的描述。
    • "text": 实际要执行的 GDB 命令文本。
    • "ignoreFailures": true: 指定如果这个命令失败是否应该忽略错误。

关于 “request”

launch.json 配置中的 "request" 字段定义了调试会话的类型。它有两个主要的值:

  1. "launch":告诉调试器启动一个程序实例,适用于当你想从头开始调试程序时。
  2. "attach":告诉调试器附加到一个已经运行的程序实例,适用于调试已经启动的进程。

某些调试器和语言扩展可能支持更多的 "request" 类型,例如 "test" 或者其他自定义请求,但 "launch""attach" 是最常见的。

  • attach类型
    • 介绍

      attach类型,可以让GDB链接到一个已经在运行的程序中进行调试,调试的手段与launch模式下一样,包括设定断点,查看变量等。但是“attach”模式进行调试的主要好处就是能够在程序已经运行的情况下开始调试,而无需重新启动程序。这在下列情况中特别有用:

      1. 程序已经运行:当您想要调试的程序已经在运行,并且不能或不方便重新启动时。这可能是因为程序需要长时间运行才能到达需要调试的状态,或者它正在处理实时数据。
      2. 生产环境的问题:特别是在生产环境中,有时候您可能无法重现问题,需要直接在生产服务器上进行调试。此时,“attach”模式允许您连接到生产服务器上的进程,直接进行调试。
      3. 服务和守护进程:对于服务和守护进程,这些程序通常由系统启动,不容易从外部启动调试会话。附加调试允许您连接到这些已经运行的服务进行调试。
      4. 远程进程:对于在远程服务器上运行的进程,您可以通过远程调试工具附加到这些进程,而不需要在服务器上直接操作。

      在“attach”模式下,调试器提供的功能(如设置断点、查看变量值、单步执行等)与在“launch”模式下启动调试会话时相同。所以,从调试功能上看,“attach”模式与“launch”模式提供了相同的调试能力,只是在操作上有所不同。

    • 步骤

      让我们以一个简单的C++程序为例,来说明如何使用**attach**模式进行调试。假设你有一个长时间运行的C++应用程序,该程序偶尔会出现一个难以复现的错误,你希望在错误发生时附加调试器来观察发生了什么

      首先,这是你的C++程序(假设文件名为main.cpp):

      #include <iostream>#include <thread>#include <chrono>void longRunningFunction() {
          for (int i = 0; i < 100; ++i) {
              std::this_thread::sleep_for(std::chrono::seconds(1));
              std::cout << "Running iteration " << i << std::endl;
          }
      }
      
      int main() {
          std::cout << "Process ID: " << getpid() << std::endl;
          longRunningFunction();
          return 0;
      }
      

      这个程序会运行一个循环,每秒打印一次输出。我们在输出中包含了进程ID,这样你就可以知道应该附加到哪个进程。

      你可以编译这个程序,然后运行它:

      g++ main.cpp -o myapp -std=c++11 -pthread
      ./myapp
      

      程序会开始运行并打印它的进程ID。

      现在,打开VS Code,创建一个launch.json文件,并添加一个attach配置:

      {
          "version": "0.2.0",
          "configurations": [
              {
                  "name": "C++ Attach",
                  "type": "cppdbg",
                  "request": "attach",
                  "program": "${workspaceFolder}/myapp",
                  "processId": "${command:pickProcess}",
                  "MIMode": "gdb",
                  "miDebuggerPath": "/usr/bin/gdb"
              }
          ]
      }
      

      注意processId设置为${command:pickProcess},这意味着VS Code会在你启动调试会话时弹出一个窗口,让你选择一个进程ID来附加。

      当你准备好附加调试器时:

      1. 在VS Code中选择“Run” > “Start Debugging”或按F5。
      2. 选择“C++ Attach”配置。
      3. VS Code会弹出一个窗口让你选择一个进程。输入或选择你的应用程序的进程ID。
      4. 现在调试器附加到了你的应用程序,你可以设置断点、检查变量、查看调用堆栈等。

      通过这种方式,你可以在程序运行到特定状态时开始调试,而不需要从头开始运行程序。这对于调试生产环境中的服务或长时间运行的进程特别有用。

关于变量 ${workspaceFolder}

${workspaceFolder} 是 VS Code 中的一个内置变量,代表当前打开的工作区(workspace)的根文件夹路径。这个变量的值是自动设置的,基于你用 VS Code 打开的文件夹。

  • 如果你通过 “File > Open Folder” 打开了一个文件夹,那么这个文件夹就是 ${workspaceFolder} 的值。
  • 如果你是在一个多根工作区环境中(即打开了多个文件夹),${workspaceFolder} 表示当前活动文件所在的根文件夹。

你不能直接在 launch.json 文件中更改 ${workspaceFolder} 变量的值,因为它是由 VS Code 根据你打开的工作区动态确定的。

如果需要特定的工作目录,你可以直接在 "cwd" 字段中指定路径,而不是使用 ${workspaceFolder} 变量,例如:


"cwd": "D:\\MyProjects\\MyApp"

请记住,当你使用特定路径而不是 ${workspaceFolder} 变量时,你的配置将不再是可移植的,这意味着在不同的机器或环境中可能需要手动调整路径。

还有哪些调试器

调试器是用来提供运行时程序调试功能的软件工具。不同的编程语言和开发环境支持不同的调试器。以下是一些常见的调试器:

  1. GDB (GNU Debugger):用于调试C和C++语言编写的程序。
  2. LLDB:LLVM项目的调试器,也主要用于C和C++语言。
  3. Visual Studio 调试器:集成在Visual Studio IDE中,支持多种语言,包括C#、C++、VB.NET等。
  4. Xcode 调试器:集成在Xcode中,主要用于Objective-C和Swift语言。
  5. PDB (Python Debugger):用于调试Python程序。
  6. Node.js Inspector:用于调试Node.js应用程序。

关于多根工作区

将两个独立的项目(目录是完全独立的,配置也可以独立),统一到一个工作区中,这种工作区就叫做多根工作区。

在这种多根工作区中,每个根目录可以代表一个独立的项目,它们在 VS Code 的界面中是并列显示的,但都在同一个编辑器窗口中进行管理。

  • 步骤

    如果你想将两个子项目配置为多根工作区的两个独立根目录,你需要:

    1. 在VS Code中打开任意一个子文件夹作为工作区。
    2. 点击“File”菜单,选择“Add Folder to Workspace…”然后选择另一个子文件夹。
    3. 通过“File”菜单选择“Save Workspace As…”保存你的多根工作区配置。

    这样,你就有了一个包含两个独立项目的多根工作区,每个项目都可以有自己的配置,并且它们在VS Code的界面中是并列的。

  • 优势

    1. 集中管理:能够在单个 VS Code 窗口中管理多个项目,而不需要为每个项目打开一个新的窗口。
    2. 共享配置:可以有一个共享的设置和扩展推荐,这对于涉及多个相关项目或服务的大型应用程序特别有用。
    3. 独立配置:尽管有共享的设置,每个项目依然可以有自己的专属配置,如特定的调试设置、任务和插件。
    4. 便捷的源码操作:可以轻松地在项目之间拖放文件,或在不同项目的文件之间进行比较和引用。
    5. 提高工作效率:在多个项目之间切换非常方便,不需要重新打开或重新布局窗口。
    6. 搜索和导航:能够跨所有打开的项目进行搜索和导航,这在处理多个库或服务时特别有用。
    7. 版本控制:如果每个根目录都是一个独立的版本控制仓库,VS Code可以同时显示每个仓库的源代码管理状态。
    8. 插件作用域:某些插件可以配置为只在特定的根目录中运行,从而允许对插件的行为进行更精细的控制。

tasks.json

这个文件定义了任务(比如编译,构建、测试或部署你的代码),这些任务可以通过VS Code的命令面板执行。你可以配置任务来运行构建系统、调用外部脚本、运行测试套件等。

常用配置

  • "type": "cppbuild": 指定任务的类型。这里是**cppbuild**,表示这是一个C++编译任务。
  • "label": "C/C++: g++.exe 生成活动文件": 这是任务的名称,显示在VS Code的任务运行菜单中。这个名字可以是任意的,描述了任务的作用。
  • "command": "D:\\Program Files (x86)\\msys64\\mingw64\\bin\\g++.exe": 指定执行的命令,这里是g++编译器的完整路径。这条命令用于编译C++源代码文件。
  • "args": 这是传递给命令的参数列表。
    • "-fdiagnostics-color=always": 强制编译器总是在诊断输出(比如错误和警告)中使用颜色,这可以帮助识别问题。
    • "-g": 在生成的可执行文件中包含调试信息,这对于后续的调试非常重要。
    • "${file}": 这是一个变量,代表当前在VS Code中打开的文件。这意味着这个任务将编译当前文件。
    • "-o": 指定输出文件的选项。
    • "${fileDirname}\\${fileBasenameNoExtension}.exe": 这是输出文件的路径和名称。它使用了几个变量来构建路径:**${fileDirname}是当前文件的目录,${fileBasenameNoExtension}是不带扩展名的文件名。最后,加上.exe**扩展名来生成Windows可执行文件。
  • "options": 包含了额外的配置选项。
    • "cwd": "${fileDirname}": 指定任务运行时的当前工作目录。**${fileDirname}**变量使得g++在源文件所在的目录下执行。
  • "problemMatcher": 用于将编译器输出中的错误和警告与VS Code的问题面板关联起来。**"$gcc"**是一个预定义的问题匹配器,适用于GCC/G++编译器的输出。
  • "group": 定义了任务的分组信息。
    • "kind": "build": 表示这个任务是一个构建任务。
    • "isDefault": true: 表示这是默认的构建任务,当你按下**Ctrl+Shift+B(或者Cmd+Shift+B**在macOS上)时会执行这个任务。
  • "detail": "调试器生成的任务。": 提供了任务的详细描述。
  • "version": "2.0.0": 指定了任务配置的版本号。

c_cpp_properties.json

这个文件用于配置C/C++插件的属性,比如包括哪些头文件路径(includePath)、定义哪些预处理器宏(defines)、使用哪种C/C++标准(cStandard/cppStandard)、选择哪个编译器路径(compilerPath)等。它帮助VS Code正确地为代码提供智能提示、代码导航和语法高亮。

settings.json

这个文件包含了编辑器的工作区设置,比如字体大小、缩进大小、是否启用自动保存等。这些设置可以覆盖全局用户设置,只对当前工作区有效。

常见问题

当点击“调试”/“运行”时发生了什么?

  • 调试:当你点击“调试”,VS Code会启动配置在**launch.json**文件中的调试器(比如GDB或LLDB,取决于你的配置和使用的平台)。调试器会启动编译出的程序,并在指定的断点处暂停执行,让你可以查看变量的值、执行堆栈、内存状态等。对于C++程序,确实常用GDB或LLDB作为调试器。
  • 运行:点击“运行”通常意味着直接启动编译出的程序,而不通过调试器。在VS Code中,这可能通过配置在**tasks.json**中的任务来实现,比如一个编译任务后跟一个执行编译结果的任务。

task.json中只指定了编译器gcc,没有指定链接器,那系统怎么知道使用哪个链接器呢?g++有链接的功能么?

是的,g++ 实际上不仅仅是一个编译器,它同时也具备链接器的功能。当你使用 g++ 来编译C++程序时,g++ 会在编译源代码文件(.cpp 文件)生成目标文件(.o.obj 文件)之后,自动调用链接器将这些目标文件链接成最终的可执行文件。

tasks.json 中,当你指定了 g++.exe 作为 command 并提供了一系列的 args(参数)时,如果参数中包括了多个源文件或至少一个目标文件,g++ 会在编译完成后自动执行链接步骤。这个过程是自动的,基于你提供的命令行参数,g++ 能够理解你的意图是仅编译、仅链接,还是编译后链接。

链接器的选择

g++ 调用的链接器通常是 GNU 的 ld,这是 GNU 项目的标准链接器。在大多数Linux系统和使用GCC的环境中,ld 被用作默认的链接器。g++ 会传递适当的参数给 ld,以确保C++标准库和其他库被正确链接。

在Windows上,当使用MinGW(一个Windows平台上的GCC移植)时,g++ 同样会调用 ld,但配置为支持Windows平台和PE(可执行文件)格式。

如何知道使用了哪个链接器

虽然在 tasks.json 中没有直接指定链接器,但通过查看 g++ 的文档和命令行参数(使用 g++ -v 来查看详细的编译和链接过程),你可以得知 g++ 在背后使用了哪个链接器以及如何调用它。

总结

  • g++ 在编译C++程序时同时承担了编译器和链接器的角色。
  • 通过在 tasks.json 中配置 g++ 命令和参数,g++ 会自动处理编译和链接步骤。
  • 链接过程通常是隐式进行的,g++ 会根据提供的源文件和目标文件参数自动执行链接。
  • g++ 默认使用的链接器是 GNU 的 ld,它被配置为支持特定平台的链接需求。

为什么不需要像java去指定库的环境变量?

C++编译器(如g++或clang++)通常已经配置好了标准库的路径,所以你不需要像设置JDK那样设置环境变量。当你编译一个程序时,编译器知道如何找到它需要的库。

不同的编译器通常会配有它们自己的标准 C++ 库实现,或者选择使用现有的某个版本。这些库实现了 C++ 标准中定义的功能,包括数据结构、算法、输入/输出操作等。这些库之间在性能、扩展功能和兼容性方面可能会有所不同。

几个常见的 C++ 标准库实现包括:

  1. libstdc++: GNU 编译器集合(GCC)所使用的 C++ 标准库。它广泛用于 Linux 系统和其他 Unix-like 系统,以及使用 MinGW 或 Cygwin 在 Windows 上的 GCC 版本。
  2. libc++: LLVM 项目的 C++ 标准库实现,与 Clang 编译器一起使用。它旨在高度遵循 C++ 标准,并且在性能和内存占用方面进行了优化。
  3. Microsoft STL (MS STL): Microsoft Visual C++(MSVC)编译器使用的 C++ 标准库。它是 Visual Studio 开发环境的一部分,并且专门为 Windows 平台优化。
  4. STLPort: 一个独立的、跨平台的 C++ 标准库实现,可以用于不同的编译器和平台。

这些库之间的主要不同可能包括:

  • 性能: 某些实现可能在特定类型的操作上进行了优化,比如字符串处理或容器操作。
  • 扩展: 虽然所有标准库都实现了 C++ 标准中定义的接口,但某些库可能提供额外的非标准扩展。
  • 兼容性: 特定的库版本可能支持特定版本的 C++ 标准(如 C++11、C++14、C++17、C++20)。
  • 平台支持: 一些库可能针对特定操作系统或硬件架构进行了特别的调整和优化。
  • 错误处理: 不同的库可能在出现异常或错误时有不同的行为。
  • 调试支持: 在调试模式下,一些库提供额外的检查或调试信息。

选择哪个标准库实现,通常取决于所使用的编译器和目标平台。大多数情况下,开发者会使用默认配套的标准库,因为它通常是为特定编译器或平台优化过的。然而,在某些跨平台项目中,可能会选择特定的标准库实现来确保一致的行为。

如果你使用的是第三方库,那么你可能需要指定这些库的路径(使用-I来指定头文件路径,使用-L-l来指定库文件的路径和名称)。

task中设置头文件引用

"tasks": [
        {
            "type": "cppbuild",
            "label": "C/C++: g++.exe 生成活动文件",
            "command": "D:\\Program Files (x86)\\msys64\\mingw64\\bin\\g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                "${workspaceFolder}\\main.cpp",
                "${workspaceFolder}\\testNUllPointer.cpp",
                "-I",
                "${workspaceFolder}/include",
                "-o",
                "${fileDirname}\\${fileBasenameNoExtension}.exe"
            ],
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "detail": "调试器生成的任务。"
        }
    ],

如果要编译多个源文件话,怎么设置呢?

要编译多个源文件到一个目标文件,您需要在 tasks.jsonargs 部分列出所有的源文件,然后指定输出的目标文件名。由于 ${file} 变量仅代表当前活动文件,它不能直接用来指定多个源文件。相反,您需要手动指定源文件的路径,或者使用通配符(取决于您的构建系统是否支持它)。

假设您的项目有两个源文件 main.cpphelper.cpp,并且您想将它们编译到一个名为 app.exe 的目标文件中。下面是如何设置 tasks.json 文件的示例:

{
    "tasks": [
        {
            "type": "cppbuild",
            "label": "Build app.exe",
            "command": "D:\\Program Files (x86)\\msys64\\mingw64\\bin\\g++.exe",
            "args": [
                "-fdiagnostics-color=always",
                "-g",
                **"${workspaceFolder}\\main.cpp"**,
                **"${workspaceFolder}\\helper.cpp",**
                "-o",
                **"${workspaceFolder}\\app.exe"**
            ],
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build",
                "isDefault": true},
            "detail": "编译 main.cpp 和 helper.cpp 到 app.exe。"
        }
    ],
    "version": "2.0.0"
}

请注意几个关键点:

  • "args": 这里您列出了所有要编译的源文件的路径。${workspaceFolder} 变量代表当前工作区的根目录,确保无论当前活动文件是什么,都会编译指定的源文件。
  • 最后的 o 参数后面指定了输出的目标文件名和路径。

这种方法适用于小到中型的项目,其中只有少数几个源文件需要编译。对于更大的项目,手动列出所有源文件可能变得不实用。在这种情况下,您可能需要使用一个更高级的构建系统(如 Make、CMake、MSBuild 等),它可以自动处理源文件的发现和管理编译依赖关系。

如果您的构建系统或命令行工具支持通配符,您也可以使用类似 "${workspaceFolder}\\*.cpp" 的方式来指定源文件,但请注意,并非所有工具和环境都支持这种语法。

参考

https://code.visualstudio.com/docs/cpp/config-mingw

  • 26
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值