HOWTO · Bash

如何在 Bash 指令碼中執行 GDB

以除錯符號編譯 C 程式、從 Bash 在 GDB 下執行它、傳遞程式引數,並自動化除錯器命令。

本頁內容

若要從 Bash 在 GDB 下執行程式,請使用 --args 呼叫 gdb,其後接上可執行檔及其引數。當指令碼應自動啟動程式時,加入 -ex run;若不加入,GDB 會開啟其提示符並等待命令。本指南會準備一個小型 C 程式、安全地建構命令,並展示互動式、中斷點與命令檔三種工作流程。為本文提供的執行時期環境不包含 GDB,因此下面的除錯器命令僅供記錄,並不作為已執行的輸出呈現。

為 GDB 準備程式

下面的範例將一個小型 C 程式寫入暫存目錄,使用 GCC 的 -g 選項對其進行編譯,然後帶一個引數執行它。除錯符號使 GDB 能夠將機器指令與原始碼行和變數關聯起來。指令碼結束時,暫存檔案會被刪除。

set -eu
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
cat > "$workdir/example.c" <<'C'
#include <stdio.h>

int main(int argc, char **argv) {
    if (argc > 1) {
        printf("Argument: %s\n", argv[1]);
    }
    return 0;
}
C
gcc -g -o "$workdir/example" "$workdir/example.c"
cd "$workdir"
program=./example
"$program" hello
printf 'gdb --quiet -ex run --args %s hello\n' "$program"
Argument: hello
gdb --quiet -ex run --args ./example hello

此可執行檔接受一個可選值;此處會印出 hello。啟動 GDB 時,請在 --args 之後使用相同的可執行檔路徑和引數。下面的 GDB 命令要求執行它們的機器上安裝有 GDB 和已編譯的可執行檔。

從 Bash 指令碼執行 GDB

Bash 指令碼可以將可執行檔和引數儲存在變數中,然後在 --args 之後傳遞它們。前面的範例預覽了組裝好的命令,無需安裝 GDB。若要從指令碼啟動真正的除錯工作階段,請使用 gdb --quiet -ex run --args "$program" "$argument"。--quiet 選項會抑制 GDB 的介紹訊息,而 -ex 會執行其後的 GDB 命令。-ex run 會啟動程式;省略它則會讓 GDB 停在 (gdb) 提示符處。若要進行互動,請省略 -ex run 並在該提示符處輸入 run。請為變數展開加上引號,使包含空格的引數仍保持為單一引數。這些除錯器呼叫要求執行指令碼的機器上安裝有 GDB 和已編譯的 example 可執行檔。

設定中斷點並檢查執行過程

若要在程式進入 main 時暫停,請在 -ex run 之前加入 -ex 'break main',例如:gdb --quiet -ex 'break main' -ex run --args ./example hello。GDB 會在執行 main 的函式主體之前停在中斷點處。在提示符處,使用 print argc 和 print argv[1] 檢查引數,然後使用 continue 繼續。bt 命令會印出目前的呼叫堆疊;它在執行暫停時(例如在中斷點處或當機之後)非常有用。已經結束的正常執行沒有可供檢查的現用呼叫堆疊。

使用命令檔自動化 GDB

對於可重複的除錯步驟,請將 GDB 命令放入名為 gdb_commands.txt 的純文字檔案中:

break main

run

print argc

使用 gdb --quiet -x gdb_commands.txt --args ./example hello 載入該檔案。GDB 會依序處理所列命令:在 main 處停止、執行程式,然後印出 argc。對於內嵌在 Bash 指令碼中的短命令序列,請使用 -ex;對於儲存在單獨檔案中的較長或可重複使用的序列,請使用 -x。命令檔包含 GDB 命令,而 --args 提供可執行檔和程式的引數。