檢視原始碼 除錯器

入門

若要使用除錯器,基本步驟如下:

步驟 1. 呼叫 debugger:start() 來啟動除錯器。

監控視窗會顯示所有被除錯的程序、已解釋的模組以及選取的選項的相關資訊。一開始通常沒有被除錯的程序。首先,必須指定要除錯(也稱為解釋)哪些模組。請依照下列步驟進行:

步驟 2. 在監控視窗中選取模組 > 解釋...

這時會顯示解釋模組視窗

步驟 3. 從「解釋」對話方塊視窗中選取適當的模組。

注意

只有使用選項 debug_info 設定編譯的模組才能被解釋。無法解釋的模組會以括號括住顯示在「解釋模組」視窗中。

步驟 4. 在監控視窗中,選取模組 > 要解釋的模組 > 檢視

原始碼檔案的內容會顯示在檢視模組視窗中。

步驟 5. 設定中斷點(如果有的話)。

步驟 6. 從 Erlang shell 以正常方式啟動要除錯的程式。

所有在已解釋模組中執行程式碼的程序都會顯示在監控視窗中。

步驟 7. 若要附加到其中一個程序,請按兩下該程序,或選取該程序,然後選擇程序 > 附加。附加到程序會為該程序開啟一個附加程序視窗

步驟 8. 在「附加程序」視窗中,您可以控制程序執行、檢查變數值、設定中斷點等等。

中斷點和中斷對話方塊視窗

一旦解釋了適當的模組,就可以在原始碼的相關位置設定中斷點。中斷點是以行為單位指定的。當程序到達中斷點時,它會停止並等待使用者發出命令(步驟略過繼續 ...)。

注意

當程序到達中斷點時,只會停止該程序。其他程序不受影響。

中斷點是使用監控視窗、「檢視模組」視窗或「附加程序」視窗的「中斷」選單來建立和刪除的。

可執行行

若要生效,中斷點必須設定在可執行行上,也就是包含可執行運算式(例如比對或函式呼叫)的程式碼行。空白行或包含註解、函式標頭或 case 陳述式或 receive 陳述式中模式的行是不可執行的。

在下列範例中,第 2、4、6、8 和 11 行是可執行行

1: is_loaded(Module,Compiled) ->
2:   case get_file(Module,Compiled) of
3:     {ok,File} ->
4:       case code:which(Module) of
5:         ?TAG ->
6:           {loaded,File};
7:         _ ->
8:           unloaded
9:       end;
10:    false ->
11:      false
12:  end.

狀態和觸發動作

中斷點可以是啟用停用。停用的中斷點會被忽略。

每個中斷點都有一個觸發動作,指定當程序到達該中斷點(並停止)時會發生什麼事

  • 啟用 - 中斷點保持啟用(預設)。
  • 停用 - 中斷點會變成停用。
  • 刪除 - 中斷點會被刪除。

行中斷點

行中斷點是在模組中的特定行建立的。

Line Break Dialog Window

按一下右鍵模組項目可開啟快顯選單,從中可以選取適當的模組。

當模組顯示在「檢視模組」視窗或「附加程序」視窗中時,也可以按兩下該行來建立(和刪除)行中斷點。

條件中斷點

條件中斷點是在模組中的特定行建立的,但只有在指定的條件為 true 時,到達中斷點的程序才會停止。

條件是由使用者指定為模組名稱 CModule 和函式名稱 CFunction。當程序到達中斷點時,會評估 CModule:CFunction(Bindings)。只有在此函式呼叫傳回 true 時,程序才會停止。如果函式呼叫傳回 false,則會自動忽略中斷點。

Bindings 是變數繫結的清單。若要擷取 Variable(以原子形式給定)的值,請使用函式 int:get_binding(Variable, Bindings)。該函式會傳回 unbound{value,Value}

Conditional Break Dialog Window

按一下右鍵模組項目可開啟快顯選單,從中可以選取適當的模組。

範例

在模組 fact 的第 6 行新增一個呼叫 c_test:c_break/1 的條件中斷點。每次到達中斷點時,都會呼叫該函式。當 N 等於 3 時,函式會傳回 true,而程序會停止。

摘錄自 fact.erl

5. fac(0) -> 1;
6. fac(N) when N > 0, is_integer(N) -> N * fac(N-1).

c_test:c_break/1 的定義

-module(c_test).
-export([c_break/1]).

c_break(Bindings) ->
    case int:get_binding('N', Bindings) of
        {value, 3} ->
            true;
        _ ->
            false
    end.

函式中斷點

函式中斷點是一組行中斷點,每個中斷點都位於指定函式中每個子句的第一行。

Function Break Dialog Window

若要開啟快顯選單,從中可以選取適當的模組,請按一下右鍵模組項目。

若要顯示清單方塊中模組的所有函式,請在指定模組名稱後,按一下確定按鈕(或按下 ReturnTab 鍵)。

堆疊追蹤

Erlang 模擬器會追蹤堆疊追蹤,也就是最近函式呼叫的相關資訊。如果發生錯誤,例如,會使用此資訊

1> catch a+1.
{'EXIT',{badarith,[{erlang,'+',[a,1],[]},
                   {erl_eval,do_apply,6,[{file,"erl_eval.erl"},{line,573}]},
                   {erl_eval,expr,5,[{file,"erl_eval.erl"},{line,357}]},
                   {shell,exprs,7,[{file,"shell.erl"},{line,674}]},
                   {shell,eval_exprs,7,[{file,"shell.erl"},{line,629}]},
                   {shell,eval_loop,3,[{file,"shell.erl"},{line,614}]}]}}

如需堆疊追蹤的詳細資訊,請參閱 Erlang 參考手冊中的錯誤和錯誤處理一節。

除錯器會追蹤最近呼叫的已解釋函式,來模擬堆疊追蹤。(無法使用真正的堆疊追蹤,因為它顯示的是呼叫了除錯器的哪些函式,而不是哪些已解釋的函式。)

此資訊可用於使用附加程序視窗中的上一步下一步按鈕來追蹤函式呼叫鏈。

根據預設,除錯器只會儲存遞迴函式呼叫的相關資訊,也就是尚未傳回值的函式呼叫(選項為開啟堆疊,無尾呼叫)。

但是,有時儲存所有呼叫(甚至是尾遞迴呼叫)可能會很有用。這可以使用選項開啟堆疊,含尾呼叫來完成。請注意,當有許多尾遞迴呼叫時,此選項會消耗更多記憶體並減慢已解釋函式的執行速度。

若要關閉除錯器堆疊追蹤功能,請選取選項關閉堆疊

注意

如果發生錯誤,堆疊追蹤在這種情況下會變成空白。

如需關於如何變更堆疊追蹤選項的資訊,請參閱監控視窗一節。

監控視窗

監控視窗是除錯器的主要視窗,並會顯示下列內容

  • 一個包含所有已解釋模組名稱的清單方塊

    按兩下模組會顯示「檢視模組」視窗。

  • 選取了哪些選項

  • 所有已除錯程序的相關資訊,也就是所有在已解釋模組中執行程式碼的程序或已經執行程式碼的程序

Monitor Window

自動附加方塊、堆疊追蹤標籤、回溯大小標籤和字串方塊會顯示一些已設定的選項。如需這些選項的詳細資訊,請參閱選項選單一節。

程序格線

  • Pid - 程序識別碼。

  • 初始呼叫 - 這個程序首次呼叫已解釋的函式。(模組:函式/引數數量

  • 名稱 - 登錄的名稱(如果有的話)。如果沒有顯示登錄的名稱,可能是除錯器在登錄名稱之前就已收到程序的相關資訊。請嘗試選取編輯 > 重新整理

  • 狀態 - 目前的狀態,可以是下列其中之一:

    • 閒置 - 已解釋的函式呼叫已傳回值,而程序不再執行已解釋的程式碼。

    • 執行中 - 程序正在執行。

    • 等待中 - 程序正在 receive 陳述式中等待。

    • 中斷 - 程序停止在中斷點。

    • 結束 - 程序已終止。

    • no_conn - 沒有與程序所在節點的連線。

  • 資訊 - 其他資訊(如果有的話)。如果程序停止在中斷點,則欄位會包含位置 {模組,行} 的相關資訊。如果程序已終止,則欄位會包含結束原因。

檔案選單

  • 載入設定... - 嘗試從先前使用儲存設定...(見下方)儲存的檔案載入和還原除錯器設定。任何錯誤都會自動忽略。

    請注意,Erlang/OTP R16B01 或更新版本儲存的設定無法由 Erlang/OTP R16B 或更早版本讀取。

  • 儲存設定... - 將除錯器設定儲存至檔案。設定包含已解釋的檔案、中斷點和選取的選項集合。設定可以在稍後的除錯器工作階段中使用載入設定...(見上方)還原。任何錯誤都會自動忽略。

  • 結束 - 停止除錯器。

編輯選單

  • 重新整理 - 更新已除錯程序的相關資訊。所有已終止程序的相關資訊都會從視窗中移除。所有已終止程序的「附加程序」視窗都會關閉。

  • 全部終止 - 使用 exit(Pid, kill) 終止視窗中列出的所有程序。

模組選單

  • 解釋... - 開啟解釋模組視窗,可以在其中指定要解釋的新模組。

  • 全部刪除 - 停止解釋所有模組。在已解釋模組中執行的程序會終止。

對於每個已解釋的模組,會在模組選單中新增一個對應的項目,其中包含下列子選單:

  • 刪除 - 停止解釋選取的模組。在此模組中執行的程序會終止。

  • 檢視 - 開啟檢視模組視窗,顯示選取模組的內容。

程序選單

下列選單項目適用於目前選取的程序,前提是該程序已在斷點停止(詳細資訊請參閱附加程序視窗章節)。

  • 單步執行

  • 下一步

  • 繼續

  • 完成

下列選單項目適用於目前選取的程序。

斷點選單

此選單中的項目用於建立和刪除斷點。詳細資訊請參閱斷點章節。

  • 行斷點... - 設定行斷點。

  • 條件斷點... - 設定條件斷點。

  • 函數斷點... - 設定函數斷點。

  • 啟用全部 - 啟用所有斷點。

  • 停用全部 - 停用所有斷點。

  • 刪除全部 - 移除所有斷點。

對於每個斷點,都會在斷點選單中新增一個對應的項目,從該項目可以停用、啟用或刪除斷點,並變更其觸發動作。

選項選單

  • 追蹤視窗 - 設定附加程序視窗中要顯示的區域。不影響現有的「附加程序」視窗。

  • 自動附加 - 設定要自動附加偵錯程序的事件。會影響現有的偵錯程序。

    • 首次呼叫 - 程序首次呼叫解譯模組中的函式時。
    • 結束時 - 程序終止時。
    • 在斷點時 - 當程序到達斷點時。
  • 堆疊追蹤 - 設定堆疊追蹤選項,請參閱堆疊追蹤章節。不影響現有的偵錯程序。

    • 啟用堆疊,尾端 - 儲存所有目前呼叫的相關資訊。
    • 啟用堆疊,無尾端 - 儲存目前呼叫的相關資訊,當進行尾端遞迴呼叫時,會捨棄先前的資訊。
    • 停用堆疊 - 不儲存任何目前呼叫的相關資訊。
  • 字串 - 設定要以字串形式列印的整數列表。不影響現有的偵錯程序。

    • 使用 +pc 旗標的範圍 - 使用 erl(1) 旗標 +pc 設定的可列印字元範圍。
  • 回溯追蹤大小... - 設定從「附加程序」視窗檢查呼叫堆疊時要擷取的呼叫框架數量。不影響現有的「附加程序」視窗。

視窗選單

包含每個開啟的「除錯器」視窗的選單項目。選取其中一個項目會提高對應的視窗。

說明選單

  • 說明 - 顯示「除錯器」文件。此功能需要網頁瀏覽器。

解譯模組視窗

「解譯模組」視窗用於選取要解譯的模組。初始時,此視窗會顯示目前工作目錄的模組(erl 檔案)和子目錄。

可解譯的模組是指其 .beam 檔案(以設定 debug_info 選項編譯)位於與原始碼相同的目錄,或位於其旁邊的 ebin 目錄中的模組。

未符合這些要求的模組是不可解譯的,因此會顯示在括號內。

選項 debug_info 會導致將偵錯資訊抽象程式碼新增至 .beam 檔案。這會增加檔案大小,並允許重建原始碼。因此,建議不要在用於目標系統的程式碼中包含偵錯資訊。

以下是如何使用 erlc 編譯包含偵錯資訊的程式碼的範例。

% erlc +debug_info module.erl

以下是如何從 Erlang shell 編譯包含偵錯資訊的程式碼的範例。

4> c(module, debug_info).

Interpret Modules Window

若要瀏覽檔案階層並解譯適當的模組,請選取模組名稱並按一下選擇(或按下 Enter 鍵),或按兩下模組名稱。已解譯的模組類型為 erl src

若要解譯選定目錄中顯示的所有模組,請按一下全部

若要關閉視窗,請按一下完成

注意

當「除錯器」以全域模式啟動時(這是預設值,請參閱 debugger:start/0),為解譯新增(或刪除)的模組會新增(或刪除)到所有已知的 Erlang 節點。

附加程序視窗

從「附加程序」視窗中,您可以與偵錯的程序互動。每個已附加的程序都會開啟一個視窗。請注意,當附加到程序時,其執行會自動停止。

Attach Process Window

此視窗分為以下五個部分:

  • 程式碼區域,顯示正在執行的程式碼。程式碼會縮排,而且每行都會加上行號。如果程序執行停止,則目前的行會標記為 -->。行上現有的斷點會標記為停止符號。在圖例中顯示的範例中,執行在 fac/1 執行前停止在第 6 行。

    作用中的斷點會以紅色顯示,而非作用中的斷點則以藍色顯示。

  • 按鈕區域,包含可快速存取程序選單中常用功能的按鈕。

  • 評估器區域,您可以在其中評估偵錯程序內容中的函式(如果該程序執行停止)。

  • 繫結區域,顯示所有變數繫結。如果您按一下變數名稱,則值會顯示在評估器區域中。按兩下變數名稱可開啟一個視窗,您可以在其中編輯變數值。但是請注意,除非 pid、連接埠、參考或 fun 值可以在執行系統中表示,否則無法編輯這些值。

  • 追蹤區域,顯示程序的追蹤輸出。

    • ++ (N) <L> - 函式呼叫,其中 N 是呼叫層級,而 L 是行號。

    • -- (N) - 函式傳回值。

      .

    • ==> Pid : Msg - 訊息 Msg 已傳送至程序 Pid

    • <== Msg - 收到訊息 Msg

    • ++ (N) receive - 在 receive 中等待。

    • ++ (N) receive with timeout - 在 receive...after 中等待。

    「追蹤」區域也會顯示「回溯追蹤」,這是堆疊上目前函式呼叫的摘要。

您可以使用選項選單來設定要顯示的區域。預設會顯示除了「追蹤」區域之外的所有區域。

檔案選單

  • 關閉 - 關閉此視窗並從程序中分離。

編輯選單

  • 前往行... - 前往指定的行號。

  • 搜尋... - 搜尋指定的字串。

程序選單

  • 單步執行 - 執行目前的程式碼行,逐步進入任何(已解譯的)函式呼叫。

  • 下一步 - 執行目前的程式碼行,並在下一行停止。

  • 繼續 - 繼續執行。

  • 完成 - 繼續執行,直到目前函式傳回。

  • 跳過 - 跳過目前的程式碼行,並在下一行停止。如果在函式主體中的最後一行使用,函式會傳回 skipped

  • 逾時 - 在執行 receive...after 陳述式時模擬逾時。

  • 停止 - 停止執行執行中的程序,也就是讓程序在斷點停止。此命令在程序下次收到訊息時生效(可見)。

  • 位置 - 確認目前執行位置在程式碼區域中是否可見。

  • 終止 - 使用 exit(Pid, kill) 終止程序。

  • 訊息 - 檢查程序的訊息佇列。佇列會顯示在評估器區域中。

  • 回溯追蹤 - 在「追蹤」區域中顯示程序的回溯追蹤,這是堆疊上目前函式呼叫的摘要。需要追蹤區域可見,且「堆疊追蹤」選項為啟用堆疊,尾端啟用堆疊,無尾端

  • 上一層 - 檢查堆疊上先前的函式呼叫,顯示位置和變數繫結。

  • 下一層 - 檢查堆疊上後續的函式呼叫,顯示位置和變數繫結。

選項選單

  • 追蹤視窗 - 設定要顯示的區域。不影響其他「附加程序」視窗。

  • 堆疊追蹤 - 與監視器視窗中的相同,但只會影響視窗附加到的偵錯程序。

  • 字串 - 與監視器視窗中的相同,但只會影響視窗附加到的偵錯程序。

  • 回溯追蹤大小... - 設定檢查呼叫堆疊時要擷取的呼叫框架數量。不影響其他「附加程序」視窗。

斷點、視窗和說明選單

斷點視窗說明選單與監視器視窗中的相同,但斷點選單僅適用於本機斷點。

檢視模組視窗

「檢視模組」視窗會顯示已解譯模組的內容,並允許您設定斷點。

View Module Window

原始碼會縮排,而且每行都會加上行號。

按一下某行會反白顯示該行,並選取該行做為斷點選單中可用斷點功能的目標。若要在某行設定行斷點,請按兩下該行。若要移除斷點,請按兩下包含現有斷點的行。

斷點會以停止符號標記。

檔案和編輯選單

檔案編輯選單與附加程序視窗中的相同。

中斷、視窗與說明選單

中斷視窗說明 選單與 監控視窗 中的相同,差別在於中斷選單僅適用於本地中斷點。

效能

直譯碼的執行速度自然比編譯過的模組慢。使用除錯器也會增加系統中的程序數量,因為每個除錯的程序都會建立另一個程序(元程序)。

還值得注意的是,具有計時器的程式在除錯時行為可能不同。當停止程序執行時(例如,在斷點處),情況尤其如此。這時,在其他正常執行的程序中可能會發生逾時。

程式碼載入機制

程式碼載入的運作方式幾乎與平常相同,只是直譯模組也會儲存在資料庫中,並且除錯的程序只會使用這個儲存的程式碼。重新直譯一個直譯模組會導致新版本也被儲存,但不會影響正在執行舊版本程式碼的現有程序。這表示 Erlang 的程式碼替換機制不適用於除錯的程序。

除錯遠端節點

透過使用 debugger:start/1,您可以指定除錯器是要在本機模式還是全域模式下啟動。

debugger:start(local | global)

如果呼叫 debugger:start/0,則除錯器將以全域模式啟動。

在本機模式下,程式碼只會在目前的節點上直譯。在全域模式下,程式碼會在所有已知的節點上直譯。其他節點上執行直譯程式碼的程序會自動顯示在監控視窗中,並且可以像任何其他除錯的程序一樣附加。

注意

不建議在網路中的多個節點上以全域模式啟動除錯器,因為節點之間會互相干擾,導致行為不一致。