🚀 在 VS Code 中免費取得

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

在本教學課程中,您將設定 Visual Studio Code 以在 Linux 上使用 GCC C++ 編譯器 (g++) 和 GDB 偵錯工具。GCC 代表 GNU Compiler Collection (GNU 編譯器套件);GDB 是 GNU 偵錯工具。

設定 VS Code 後,您將在 VS Code 中編譯和偵錯簡單的 C++ 程式。本教學課程不會教您 GCC、GDB、Ubuntu 或 C++ 語言。關於這些主題,網路上有許多優良資源。

如果您有問題,歡迎在 VS Code 文件存放庫中針對本教學課程提出問題。

先決條件

若要成功完成本教學課程,您必須執行下列操作

  1. 安裝 Visual Studio Code

  2. 安裝 VS Code 的 C++ 擴充功能。您可以在 [擴充功能] 檢視中搜尋 'c++' 來安裝 C/C++ 擴充功能 (⇧⌘X (Windows、Linux Ctrl+Shift+X))。

    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++ 建置並偵錯作用中檔案]。

    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

您可以修改 tasks.json,以使用類似 "${workspaceFolder}/*.cpp" 而非 "${file}" 的引數來建置多個 C++ 檔案。這將建置目前資料夾中的所有 .cpp 檔案。您也可以藉由將 "${fileDirname}/${fileBasenameNoExtension}" 取代為硬式編碼的檔案名稱 (例如 'helloworld.out') 來修改輸出檔案名稱。

偵錯 helloworld.cpp

若要偵錯您的程式碼,

  1. 返回 helloworld.cpp,使其成為作用中檔案。
  2. 藉由按一下編輯器邊界或在目前行上使用 F9 來設定中斷點。helloworld.cpp 中斷點的螢幕擷取畫面
  3. 從播放按鈕旁邊的下拉式選單中,選取 [偵錯 C/C++ 檔案]。播放按鈕下拉式選單的螢幕擷取畫面
  4. 從系統上偵測到的編譯器清單中選擇 [C/C++: g++ 建置並偵錯作用中檔案] (您只會在第一次執行或偵錯 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++ 建置並偵錯作用中檔案]。

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

只有當您的程式包含不在工作區或標準程式庫路徑中的標頭檔時,您才需要修改 [包含路徑] 設定。

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 _mainattempting to link with file built for unknown-unsupported file format 等) 最常見的原因是當您開始建置或開始偵錯時,helloworld.cpp 不是作用中檔案。這是因為編譯器嘗試編譯的不是原始碼,而是您的 launch.jsontasks.jsonc_cpp_properties.json 檔案。

後續步驟