參加你附近的 ,瞭解 VS Code 中的 AI 輔助開發。

在 VS Code 中於 Linux 上使用 C++

在本教程中,您將配置 Visual Studio Code 以在 Linux 上使用 GCC C++ 編譯器 (g++) 和 GDB 偵錯程式。GCC 代表 GNU 編譯器集合 (GNU Compiler Collection);GDB 是 GNU 偵錯程式 (GNU debugger)。

配置完 VS Code 後,您將在 VS Code 中編譯和除錯一個簡單的 C++ 程式。本教程不教授 GCC、GDB、Ubuntu 或 C++ 語言。關於這些主題,網上有許多優秀的資源可供查閱。

如果您遇到問題,請隨時在 VS Code 文件庫中為本教程提交 issue。

先決條件

要成功完成本教程,您必須執行以下操作

  1. 安裝 Visual Studio Code

  2. 安裝 VS Code 的 C++ 擴充套件。您可以在“擴充套件”檢視 (⇧⌘X (Windows, Linux Ctrl+Shift+X)) 中搜索“c++”來安裝 C/C++ 擴充套件。

    C/C++ extension

確保 GCC 已安裝

雖然您將使用 VS Code 編輯原始碼,但您將使用 g++ 編譯器在 Linux 上編譯原始碼。您還將使用 GDB 進行除錯。這些工具在 Ubuntu 上預設沒有安裝,因此您必須安裝它們。幸運的是,這很簡單。

首先,檢查 GCC 是否已安裝。要驗證是否安裝,請開啟一個終端視窗並輸入以下命令

gcc -v

如果未安裝 GCC,請從終端視窗執行以下命令來更新 Ubuntu 軟體包列表。過時的 Linux 發行版有時會干擾安裝新軟體包的嘗試。

sudo apt-get update

接下來用此命令安裝 GNU 編譯器工具和 GDB 偵錯程式

sudo apt-get install build-essential gdb

建立 Hello World

在終端視窗中,建立一個名為 projects 的空資料夾來存放您的 VS Code 專案。然後建立一個名為 helloworld 的子資料夾,導航到其中,並透過輸入以下命令在該資料夾中開啟 VS Code

mkdir projects
cd projects
mkdir helloworld
cd helloworld
code .

code . 命令會在當前工作資料夾中開啟 VS Code,該資料夾將成為您的“工作區”。在學習本教程的過程中,您將在工作區的 .vscode 資料夾中建立三個檔案

  • tasks.json (編譯器構建設定)
  • launch.json(偵錯程式設定)
  • c_cpp_properties.json(編譯器路徑和 IntelliSense 設定)

新增 hello world 原始碼檔案

在檔案資源管理器標題欄中,選擇 新建檔案 並將檔案命名為 helloworld.cpp

New File title bar button

貼上以下原始碼

#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    vector<string> msg {"Hello", "C++", "World", "from", "VS Code", "and the C++ extension!"};

    for (const string& word : msg)
    {
        cout << word << " ";
    }
    cout << endl;

    return 0;
}

現在按 ⌘S (Windows, Linux Ctrl+S) 儲存檔案。請注意,您的檔案會列在 VS Code 側邊欄的檔案資源管理器檢視 (⇧⌘E (Windows, Linux Ctrl+Shift+E)) 中。

File Explorer

你還可以透過在主檔案選單中勾選自動儲存來啟用自動儲存,以自動儲存你的檔案更改。

Visual Studio Code 邊緣的活動欄可讓您開啟不同的檢視,例如搜尋原始碼管理執行。您將在本教程的後面部分了解執行檢視。您可以在 VS Code 使用者介面文件中瞭解有關其他檢視的更多資訊。

注意:當您儲存或開啟 C++ 檔案時,您可能會看到來自 C/C++ 擴充套件的關於 Insiders 版本可用的通知,該版本可讓您測試新功能和修復。您可以透過選擇 X (清除通知) 來忽略此通知。

探索 IntelliSense

helloworld.cpp 檔案中,將滑鼠懸停在 vectorstring 上以檢視型別資訊。在宣告 msg 變數後,開始輸入 msg.,就像呼叫成員函式時一樣。您應該會立即看到一個顯示所有成員函式的補全列表,以及一個顯示 msg 物件型別資訊的視窗。

Statement completion IntelliSense

您可以按 Tab 鍵插入所選的成員。然後,當您新增左括號時,您將看到有關該函式所需引數的資訊。

執行 helloworld.cpp

請記住,C++ 擴充套件使用你機器上安裝的 C++ 編譯器來生成程式。在嘗試在 VS Code 中執行和除錯 helloworld.cpp 之前,請確保已安裝 C++ 編譯器。

  1. 開啟 helloworld.cpp,使其成為活動檔案。

  2. 單擊編輯器右上角的播放按鈕。

    Screenshot of helloworld.cpp and play button

  3. 從系統上檢測到的編譯器列表中選擇 g++ build and debug active file

    C++ debug configuration dropdown

你只會在第一次執行 helloworld.cpp 時被要求選擇一個編譯器。此編譯器將被設定為 tasks.json 檔案中的“預設”編譯器。

  1. 生成成功後,你的程式輸出將顯示在整合終端中。

    screenshot of program output

第一次執行程式時,C++ 擴充套件會建立 tasks.json,你會在專案中的 .vscode 資料夾中找到它。tasks.json 儲存生成配置。

你的新 tasks.json 檔案應類似於下面的 JSON

{
  "version": "2.0.0",
  "tasks": [
    {
      "type": "shell",
      "label": "C/C++: g++ build active file",
      "command": "/usr/bin/g++",
      "args": ["-g", "${file}", "-o", "${fileDirname}/${fileBasenameNoExtension}"],
      "options": {
        "cwd": "/usr/bin"
      },
      "problemMatcher": ["$gcc"],
      "group": {
        "kind": "build",
        "isDefault": true
      },
      "detail": "Task generated by Debugger."
    }
  ]
}

注意:你可以在變數參考中瞭解有關 tasks.json 變數的更多資訊。

command 設定指定要執行的程式;在本例中是 g++。args 陣列指定將傳遞給 g++ 的命令列引數。這些引數必須按照編譯器期望的順序指定。

此任務告訴 g++ 獲取活動檔案 (${file}),對其進行編譯,並在當前目錄 (${fileDirname}) 中建立一個與活動檔案同名但沒有副檔名的可執行檔案 (${fileBasenameNoExtension}),對於我們的示例,結果是 helloworld

label 值是你在任務列表中將看到的內容;你可以隨意命名。

detail 的值是您將在任務列表中看到的任務描述。強烈建議重新命名此值以將其與類似任務區分開來。

從現在開始,播放按鈕將從 tasks.json 中讀取資訊,以確定如何構建和執行你的程式。你可以在 tasks.json 中定義多個構建任務,而標記為預設的任務將被播放按鈕使用。如果你需要更改預設編譯器,可以執行任務: 配置預設生成任務。或者,你可以修改 tasks.json 檔案,並透過替換以下段落來刪除預設設定

    "group": {
        "kind": "build",
        "isDefault": true
    },

替換為

    "group": "build",

修改 tasks.json

您可以透過使用像 "${workspaceFolder}/*.cpp" 這樣的引數而不是 "${file}" 來修改您的 tasks.json 以構建多個 C++ 檔案。這將構建您當前資料夾中的所有 .cpp 檔案。您還可以透過將 "${fileDirname}/${fileBasenameNoExtension}" 替換為硬編碼的檔名(例如 'helloworld.out')來修改輸出檔名。

除錯 helloworld.cpp

要除錯你的程式碼,

  1. 回到 helloworld.cpp,使其成為活動檔案。
  2. 透過單擊編輯器邊距或在當前行使用 F9 設定斷點。helloworld.cpp 中斷點的螢幕截圖
  3. 從播放按鈕旁邊的下拉選單中,選擇除錯 C/C++ 檔案播放按鈕下拉選單的螢幕截圖
  4. 從系統上檢測到的編譯器列表中選擇 C/C++: g++ build and debug active file(只有在您第一次執行或除錯 helloworld.cpp 時,系統才會要求您選擇編譯器)。C++ 除錯配置下拉選單

播放按鈕有兩種模式:執行 C/C++ 檔案除錯 C/C++ 檔案。它將預設為上次使用的模式。如果您在播放按鈕中看到除錯圖示,您可以直接選擇播放按鈕進行除錯,而無需選擇下拉選單項。

探索偵錯程式

在開始單步除錯程式碼之前,我們花點時間注意使用者介面中的幾處變化

  • 整合終端出現在原始碼編輯器的底部。在除錯輸出選項卡中,你將看到指示偵錯程式已啟動並正在執行的輸出。

  • 編輯器會高亮顯示第 12 行,這是您在啟動偵錯程式之前設定的斷點。

    Initial breakpoint

  • 左側的執行和除錯檢視顯示除錯資訊。你將在本教程的後面看到一個示例。

  • 程式碼編輯器頂部會出現一個除錯控制面板。你可以透過抓取左側的點來在螢幕上移動它。

    Debugging controls

如果您的工作區中已有 launch.json 檔案,則播放按鈕在確定如何執行和除錯 C++ 檔案時將從中讀取。如果您沒有 launch.json,播放按鈕將即時建立一個臨時的“快速除錯”配置,從而完全無需 launch.json!

單步除錯程式碼

現在你已準備好開始單步除錯程式碼。

  1. 單擊或按下除錯控制面板中的跳過圖示。

    Step over button

    這將使程式執行推進到 for 迴圈的第一行,並跳過在建立和初始化 msg 變數時呼叫的 vectorstring 類中的所有內部函式呼叫。請注意側邊變數視窗中的變化。

    Debugging windows

  2. 再次按跳過以推進到此程式中的下一個語句(跳過用於初始化迴圈的所有內部程式碼)。現在,變數視窗顯示有關迴圈變數的資訊。

  3. 再次按單步跳過以執行 cout 語句。(請注意,C++ 擴充套件在最後一個 cout 執行之前不會向除錯控制檯列印任何輸出。)

  4. 如果你願意,可以繼續按單步跳過,直到向量中的所有單詞都列印到控制檯。但如果你好奇,可以嘗試按單步進入按鈕來單步執行 C++ 標準庫中的原始碼!

    Breakpoint in gcc standard library header

    要返回到你自己的程式碼,一種方法是繼續按單步跳過。另一種方法是在你的程式碼中設定一個斷點,方法是切換到程式碼編輯器中的 helloworld.cpp 選項卡,將插入點放在迴圈內的 cout 語句的某處,然後按 F9。左側的邊欄會出現一個紅點,表示已在此行設定了斷點。

    Breakpoint in main

    然後按 F5 從標準庫標頭檔案的當前行開始執行。執行將在 cout 處中斷。如果你願意,可以再次按 F9 來關閉斷點。

    當迴圈完成後,您可以在整合終端的除錯控制檯選項卡中看到輸出,以及 GDB 輸出的一些其他診斷資訊。

    Debug console display

設定監視

要在程式執行時跟蹤變數的值,請對該變數設定一個監視

  1. 將插入點放在迴圈內部。在監視視窗中,單擊加號,然後在文字框中輸入 word,這是迴圈變數的名稱。現在,在單步執行迴圈時檢視“監視”視窗。

    Watch window

  2. 要在執行暫停在斷點處時快速檢視任何變數的值,你可以將滑鼠指標懸停在其上方。

    Mouse hover

接下來,您將建立一個 tasks.json 檔案來告訴 VS Code 如何構建(編譯)程式。此任務將呼叫 g++ 編譯器從原始碼建立可執行檔案。

確保 helloworld.cpp 在編輯器中處於開啟狀態非常重要,因為下一步會使用編輯器中的活動檔案作為上下文來建立構建任務。

使用 launch.json 自定義除錯

當你使用播放按鈕或 F5 進行除錯時,C++ 擴充套件會即時建立一個動態除錯配置。

在某些情況下,你可能希望自定義除錯配置,例如指定在執行時傳遞給程式的引數。你可以在 launch.json 檔案中定義自定義除錯配置。

要建立 launch.json,請從播放按鈕下拉選單中選擇新增除錯配置

Add debug configuration play button menu

然後您會看到一個包含各種預定義除錯配置的下拉列表。選擇 g++ build and debug active file

C++ debug configuration dropdown

VS Code 建立一個 launch.json 檔案,它看起來像這樣

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "C/C++: g++ build and debug active file",
      "type": "cppdbg",
      "request": "launch",
      "program": "${fileDirname}/${fileBasenameNoExtension}",
      "args": [],
      "stopAtEntry": false,
      "cwd": "${workspaceFolder}",
      "environment": [],
      "externalConsole": false,
      "MIMode": "gdb",
      "miDebuggerPath": "/usr/bin/gdb",
      "setupCommands": [
        {
          "description": "Enable pretty-printing for gdb",
          "text": "-enable-pretty-printing",
          "ignoreFailures": true
        }
      ],
      "preLaunchTask": "C/C++: g++ build active file"
    }
  ]
}

在上面的 JSON 中,program 指定了您要除錯的程式。這裡它被設定為活動檔案所在的資料夾 ${fileDirname} 和不帶副檔名的活動檔名 ${fileBasenameNoExtension},如果 helloworld.cpp 是活動檔案,它將是 helloworldargs 屬性是一個在執行時傳遞給程式的引數陣列。

預設情況下,C++ 擴充套件不會向你的原始碼新增任何斷點,並且 stopAtEntry 值設定為 false

stopAtEntry 值更改為 true,以便在開始除錯時讓偵錯程式在 main 方法處停止。

從現在開始,播放按鈕和 F5 在啟動程式進行除錯時將從你的 launch.json 檔案中讀取資訊。

C/C++ 配置

如果你想對 C/C++ 擴充套件進行更多控制,可以建立一個 c_cpp_properties.json 檔案,它將允許你更改編譯器路徑、包含路徑、C++ 標準(預設為 C++17)等設定。

你可以透過從命令面板 (⇧⌘P (Windows、Linux 為 Ctrl+Shift+P)) 執行 C/C++: 編輯配置 (UI) 命令來檢視 C/C++ 配置 UI。

Command Palette

這將開啟C/C++ 配置頁面。當你在此處進行更改時,VS Code 會將它們寫入 .vscode 資料夾中名為 c_cpp_properties.json 的檔案。

IntelliSense configuration window

僅當您的程式包含不在您的工作區或標準庫路徑中的標頭檔案時,您才需要修改 Include path 設定。

Visual Studio Code 將這些設定放在 .vscode/c_cpp_properties.json 中。如果你直接開啟該檔案,它應該看起來像這樣

{
  "configurations": [
    {
      "name": "Linux",
      "includePath": ["${workspaceFolder}/**"],
      "defines": [],
      "compilerPath": "/usr/bin/gcc",
      "cStandard": "c11",
      "cppStandard": "c++17",
      "intelliSenseMode": "clang-x64"
    }
  ],
  "version": 4
}

重用您的 C++ 配置

VS Code 現在已配置為在 Linux 上使用 gcc。該配置適用於當前工作區。要重用該配置,只需將 JSON 檔案複製到新專案資料夾(工作區)的 .vscode 資料夾中,並根據需要更改原始檔和可執行檔案的名稱。

故障排除

編譯器和連結錯誤

最常見的錯誤原因(例如 undefined _main,或 attempting to link with file built for unknown-unsupported file format 等)發生在您開始構建或開始除錯時 helloworld.cpp 不是活動檔案的情況下。這是因為編譯器正在嘗試編譯非原始碼的內容,比如您的 launch.jsontasks.jsonc_cpp_properties.json 檔案。

後續步驟