模組 Printexc

module Printexc: sig .. end

用於列印例外和檢查目前呼叫堆疊的工具。


type t = exn = ..

例外值的型別。

val to_string : exn -> string

Printexc.to_string e 會回傳例外 e 的字串表示形式。

val to_string_default : exn -> string

Printexc.to_string_default e 會回傳例外 e 的字串表示形式,並忽略所有已註冊的例外印表機。

val print : ('a -> 'b) -> 'a -> 'b

Printexc.print fn x 會將 fn 套用到 x 並回傳結果。如果 fn x 的評估引發任何例外,則例外的名稱會列印到標準錯誤輸出,並且例外會再次引發。典型的用法是捕捉並報告逸出函式套用的例外。

val catch : ('a -> 'b) -> 'a -> 'b
已棄用。此函式不再需要。

Printexc.catch fn x 類似於 Printexc.print,但在列印未捕獲的例外後,會以結束代碼 2 中止程式。此函式已棄用:執行階段系統現在能夠像 Printexc.catch 一樣精確地列印未捕獲的例外。此外,呼叫 Printexc.catch 會使得使用除錯器或堆疊回溯追蹤工具追蹤例外的位置更加困難。因此,請勿在新程式碼中使用 Printexc.catch

val print_backtrace : out_channel -> unit

Printexc.print_backtrace oc 會在輸出通道 oc 上列印例外回溯追蹤。回溯追蹤會列出最近引發的例外引發的程式位置,以及它透過函式呼叫傳播的位置。

如果呼叫不在例外處理常式內,則回傳的回溯追蹤未指定。如果呼叫是在某些例外捕捉程式碼之後(在處理常式中或在符合例外處理常式期間的 when 保護中),回溯追蹤可能對應於比處理的例外更晚發生的例外。

val get_backtrace : unit -> string

Printexc.get_backtrace () 會回傳一個字串,其中包含與 Printexc.print_backtrace 將列印的相同的例外回溯追蹤。使用限制與 Printexc.print_backtrace 相同。

val record_backtrace : bool -> unit

Printexc.record_backtrace b 會開啟(如果 b = true)或關閉(如果 b = false)例外回溯追蹤的記錄。最初,不會記錄回溯追蹤,除非透過 OCAMLRUNPARAM 變數將 b 旗標提供給程式。

val backtrace_status : unit -> bool

Printexc.backtrace_status() 會在目前記錄例外回溯追蹤時回傳 true,如果未記錄則回傳 false

val register_printer : (exn -> string option) -> unit

Printexc.register_printer fn 會將 fn 註冊為例外印表機。如果印表機不知道如何轉換傳遞的例外,則印表機應回傳 None 或引發例外,如果可以轉換傳遞的例外,則回傳 Some
    s
,其中 s 是產生的字串。印表機引發的例外會被忽略。

將例外轉換為字串時,會以反向註冊順序呼叫印表機,直到印表機回傳 Some s 值為止(如果沒有此類印表機,執行階段將使用泛型印表機)。

使用此機制時,應該注意,例外回溯追蹤會附加到看到例外引發的執行緒,而不是例外本身。實際上,這表示與 fn 相關的程式碼,如果它本身先前引發過例外,則不應使用回溯追蹤。

val use_printers : exn -> string option

Printexc.use_printers e 如果沒有已註冊的印表機,則回傳 None,否則回傳 Some s,其中 s 為產生的字串。

原始回溯追蹤

type raw_backtrace 

型別 raw_backtrace 會以低階格式儲存回溯追蹤,可以使用以下的 raw_backtrace_entriesbacktrace_slots_of_raw_entry 將其轉換為可用的形式。

將回溯追蹤轉換為 backtrace_slot 比捕捉回溯追蹤慢。如果應用程式處理許多回溯追蹤,則使用 raw_backtrace 可以避免或延遲轉換。

原始回溯追蹤無法編組。如果需要編組,則應使用下一節的 backtrace_slots 函式回傳的陣列。

type raw_backtrace_entry = private int 

raw_backtrace_entryraw_backtrace 的元素。

每個 raw_backtrace_entry 都是不透明的整數,其值在不同的程式之間,甚至在同一個二進位的不同執行之間都不穩定。

可以使用以下的 backtrace_slots_of_raw_entryraw_backtrace_entry 轉換為可用的形式。請注意,由於內嵌,單個 raw_backtrace_entry 可能會轉換為多個 backtrace_slot。由於 raw_backtrace_entry 的值不穩定,因此它們無法編組。如果要轉換它們,則必須由產生它們的程序執行轉換。

同樣由於內嵌,可能會有多個不同的 raw_backtrace_entry 值轉換為相等的 backtrace_slot。但是,如果兩個 raw_backtrace_entry 作為整數相等,則它們代表相同的 backtrace_slot

val raw_backtrace_entries : raw_backtrace -> raw_backtrace_entry array
val get_raw_backtrace : unit -> raw_backtrace

Printexc.get_raw_backtrace () 會回傳與 Printexc.print_backtrace 將列印的相同的例外回溯追蹤,但採用原始格式。使用限制與 Printexc.print_backtrace 相同。

val print_raw_backtrace : out_channel -> raw_backtrace -> unit

Printexc.print_backtrace 使用的相同格式列印原始回溯追蹤。

val raw_backtrace_to_string : raw_backtrace -> string

Printexc.get_backtrace 使用的相同格式,從原始回溯追蹤回傳字串。

val raise_with_backtrace : exn -> raw_backtrace -> 'a

使用給定的原始回溯追蹤作為例外的來源,再次引發例外

目前呼叫堆疊

val get_callstack : int -> raw_backtrace

Printexc.get_callstack n 會回傳目前程式點(針對目前執行緒)呼叫堆疊頂端的描述,最多包含 n 個項目。(注意:此函式與例外完全無關,儘管它是 Printexc 模組的一部分。)

未捕獲的例外

val default_uncaught_exception_handler : exn -> raw_backtrace -> unit

Printexc.default_uncaught_exception_handler 會在標準錯誤輸出上列印例外和回溯追蹤。

val set_uncaught_exception_handler : (exn -> raw_backtrace -> unit) -> unit

Printexc.set_uncaught_exception_handler fn 會將 fn 註冊為未捕獲的例外的處理常式。預設的處理常式為 Printexc.default_uncaught_exception_handler

請注意,當呼叫 fn 時,已呼叫所有使用 at_exit 註冊的函式。因此,您必須確保 fn 寫入的任何輸出通道都會被清除。

另請注意,在互動式頂層中,使用者程式碼引發的例外不會傳遞給此函式,因為它們會由頂層本身捕捉。

如果 fn 引發例外,則傳遞給 fn 和由 fn 引發的例外都會列印其各自的回溯追蹤。

回溯追蹤資訊的操控

這些函式用於走訪原始回溯追蹤的槽,並以程式設計師友好的格式從中擷取資訊。

type backtrace_slot 

抽象型別 backtrace_slot 代表回溯追蹤的單個槽。

val backtrace_slots : raw_backtrace -> backtrace_slot array option

會回傳原始回溯追蹤的槽,如果它們中沒有任何一個包含有用的資訊,則回傳 None

在回傳的陣列中,索引 0 的槽對應於追蹤中最近的函式呼叫、引發或基本 get_backtrace 呼叫。

回傳 None 的一些可能原因如下

  • 追蹤中的任何槽都不來自使用除錯資訊編譯的模組(-g
  • 程式是未連結啟用除錯資訊的位元組碼程式(ocamlc -g
val backtrace_slots_of_raw_entry : raw_backtrace_entry -> backtrace_slot array option

會回傳單個原始回溯追蹤項目的槽,如果此項目缺少除錯資訊,則回傳 None

槽會以與 backtrace_slots 相同的順序回傳:索引 0 的槽是最近的呼叫、引發或基本呼叫,後續的槽代表呼叫端。

type location = {
   filename :string
   line_number :int
   start_char :int
   end_char :int
   end_line :int (*
  • 自從 5.2
*)
   end_col :int (*
  • 自從 5.2
*)
}

回溯追蹤中找到的位置資訊的型別。start_charend_char 是相對於 line_number 開頭的位置。end_col 是相對於 end_line 開頭的位置。

module Slot: sig .. end

原始回溯追蹤槽

type raw_backtrace_slot 

此型別用於反覆運算 raw_backtrace 的槽。對於大多數用途,backtrace_slots_of_raw_entry 更易於使用。

raw_backtrace_entry 類似,此型別的值是程序特定的,絕對不能編組,並且由於這個原因,使用它們是不安全的(編組它們可能不會失敗,但是取消編組和使用結果將會導致未定義的行為)。

此型別的元素仍然可以比較和雜湊:當兩個元素相等時,它們表示相同的原始位置(例如,在存在內嵌的情況下,反之不一定成立)。

val raw_backtrace_length : raw_backtrace -> int

raw_backtrace_length bckt 會回傳回溯追蹤 bckt 中的槽數。

val get_raw_backtrace_slot : raw_backtrace -> int -> raw_backtrace_slot

get_raw_backtrace_slot bckt pos 會回傳回溯追蹤 bckt 中位置 pos 的槽。

val convert_raw_backtrace_slot : raw_backtrace_slot -> backtrace_slot

從低階 raw_backtrace_slot 擷取使用者友好的 backtrace_slot

val get_raw_backtrace_next_slot : raw_backtrace_slot -> raw_backtrace_slot option

get_raw_backtrace_next_slot slot 會回傳內嵌的下一個槽(如果有的話)。

用於反覆運算所有框架(內嵌和非內嵌)的範例程式碼

      (* Iterate over inlined frames *)
      let rec iter_raw_backtrace_slot f slot =
        f slot;
        match get_raw_backtrace_next_slot slot with
        | None -> ()
        | Some slot' -> iter_raw_backtrace_slot f slot'

      (* Iterate over stack frames *)
      let iter_raw_backtrace f bt =
        for i = 0 to raw_backtrace_length bt - 1 do
          iter_raw_backtrace_slot f (get_raw_backtrace_slot bt i)
        done
    

例外槽

val exn_slot_id : exn -> int

Printexc.exn_slot_id 回傳一個整數,該整數在目前的執行時期中,唯一識別用於建立例外值 exn 的建構子。

val exn_slot_name : exn -> string

Printexc.exn_slot_name exn 回傳用於建立例外值 exn 的建構子的內部名稱。