檢視原始碼 錯誤與錯誤處理

術語

錯誤大致可以分為四種不同的類型

  • 編譯時錯誤 - 當編譯器無法編譯程式時,例如語法錯誤。

  • 邏輯錯誤 - 當程式的行為不如預期,但不會崩潰時。一個例子是當點擊圖形使用者介面中的按鈕時,沒有任何反應。

  • 執行時錯誤 - 當發生崩潰時。一個例子是當運算子被應用於錯誤類型的參數時。Erlang 程式語言具有內建的執行時錯誤處理功能。執行時錯誤也可以透過呼叫 error(Reason) 來模擬。執行時錯誤是 error 類別的例外。

  • 產生的錯誤 當程式碼本身呼叫 exit/1throw/1 時。產生的錯誤是 exitthrow 類別的例外。

當 Erlang 中發生例外時,會停止評估錯誤運算式的程序的執行。這被稱為*失敗*,即執行或評估*失敗*,或程序*失敗*、*終止*或*退出*。請注意,程序可能由於失敗以外的其他原因而終止/退出。

終止的程序會發出一個*退出訊號*,其中包含描述程序為何終止的*退出原因*。通常,關於任何錯誤終止的一些資訊會列印到終端機。有關終止的更多詳細資訊,請參閱程序章節中的程序終止

例外

例外是執行時錯誤產生的錯誤,並且屬於三個不同的類別,具有不同的來源。try 運算式可以區分不同的類別,而 catch 運算式則不能。trycatch運算式中描述。

類別來源
error執行時錯誤,例如,1+a,或程序呼叫了 error/1
exit程序呼叫了 exit/1
throw程序呼叫了 throw/1

表:例外類別。

以上所有例外也可以透過呼叫 erlang:raise/3 來產生。

例外由其類別、退出原因(參閱退出原因)和堆疊追蹤(有助於找到例外的程式碼位置)組成。

堆疊追蹤可以從任何例外類別的 try 運算式中繫結到變數,或者作為 catch 捕獲執行時錯誤時的退出原因的一部分。範例

> {'EXIT',{test,Stacktrace}} = (catch error(test)), Stacktrace.
[{shell,apply_fun,3,[]},
 {erl_eval,do_apply,6,[]},
 ...]
> try throw(test) catch Class:Reason:Stacktrace -> Stacktrace end.
[{shell,apply_fun,3,[]},
 {erl_eval,do_apply,6,[]},
 ...]

呼叫堆疊回溯 (堆疊追蹤)

堆疊回溯(stacktrace)是一個列表,其中包含 {Module, Function, Arity, ExtraInfo} 和/或 {Fun, Arity, ExtraInfo} 元組。元組中的 Arity 欄位可以是該函式呼叫的引數列表,而不是算數整數,具體取決於例外。

ExtraInfo 是一個(可能為空的)雙元素元組列表,以任何順序提供關於例外的額外資訊。第一個元素是一個原子,描述第二個元素中的資訊類型。可能會出現以下項目

  • error_info - 元組的第二個元素是一個 map,提供關於導致例外的額外資訊。此資訊可以透過呼叫 error/3 來建立,並由 erl_error:format_exception/4 使用。

  • file - 元組的第二個元素是一個字串(字元列表),表示函式原始檔的檔名。

  • line - 元組的第二個元素是發生例外或呼叫函式的原始檔中的行號(大於 0 的整數)。

警告

開發人員應僅將堆疊追蹤條目用於除錯目的。

VM 執行尾部呼叫最佳化,這不會向堆疊追蹤新增新條目,並且還會將堆疊追蹤限制為特定深度。此外,編譯器選項、最佳化和未來的變更可能會新增或移除堆疊追蹤條目,導致任何期望堆疊追蹤按特定順序排列或包含特定項目的程式碼失敗。

此規則的唯一例外是原因為 undeferror 類別,它保證會包含嘗試函式的 ModuleFunctionArity 作為第一個堆疊追蹤條目。

在 Erlang 中處理執行時錯誤

程序內的錯誤處理

可以使用 trycatch 來防止執行時錯誤和其他例外導致程序終止。

程序之間的錯誤處理

程序可以監視其他程序並偵測程序終止,參閱 程序

退出原因

當發生執行時錯誤時,即 error 類別的例外。退出原因是一個元組 {Reason,Stack},其中 Reason 是一個表示錯誤類型的 term

  • badarg - 不正確的引數。引數的資料類型錯誤,或格式不正確。

  • badarith - 算術運算式的引數不是數值,或運算式無法評估為有限數字。

  • {badmatch,V} - 比對運算式的評估失敗。值 V 不符合。

  • function_clause - 在評估函式呼叫時,找不到符合的函式子句。

  • {case_clause,V} - 在評估 case 運算式時,找不到符合的分支。值 V 不符合。

  • if_clause - 在評估 if 運算式時,找不到 true 分支。

  • {try_clause,V} - 在評估 try 運算式的 of 區段時,找不到符合的分支。值 V 不符合。

  • undef - 在評估函式呼叫時,找不到該函式。

  • {badfun,F} - 預期 F 是一個 fun,但事實並非如此。

  • {badarity,{Fun,Args}} - 將 fun 套用至錯誤的引數數量。

  • timeout_value - receive...after 運算式中的逾時值被評估為整數或 infinity 以外的其他內容。

  • noproc - 嘗試建立到不存在的程序或埠的 連結監控

  • noconnection - 因為無法建立節點之間的連線或連線已斷開,因此與遠端程序的連結或監控已中斷。

  • {nocatch,V} - 嘗試在 catch 之外評估 throwV 是拋出的 term。

  • system_limit - 已達到系統限制。有關系統限制的資訊,請參閱效率指南中的系統限制

Stack 是發生錯誤時正在評估的函式呼叫堆疊,以元組列表 {Module,Name,Arity,ExtraInfo} 的形式給出,最近的函式呼叫在最前面。在某些情況下,最近的函式呼叫元組可能是 {Module,Name,[Arg],ExtraInfo}