模块 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 xfn 应用于 x 并返回结果。如果 fn x 的评估引发了任何异常,则异常的名称将打印到标准错误输出,并再次引发异常。典型的用法是捕获和报告从函数应用中逃逸的异常。

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

Printexc.catch fn xPrintexc.print 相似,但在打印未捕获的异常后使用退出代码 2 终止程序。此函数已弃用:运行时系统现在能够像 Printexc.catch 一样精确地打印未捕获的异常。此外,调用 Printexc.catch 使得使用调试器或堆栈回溯工具跟踪异常位置更加困难。因此,在新代码中不要使用 Printexc.catch

val print_backtrace : out_channel -> unit

Printexc.print_backtrace oc 在输出通道 oc 上打印异常回溯。回溯列出了最近引发的异常被引发的位置以及通过函数调用传播的位置。

如果调用不在异常处理程序中,则返回的回溯是不确定的。如果调用在某些异常捕获代码之后(在处理程序之前,或在异常处理程序匹配期间的 when-guard 中),则回溯可能对应于比已处理的异常更晚的异常。

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 以及结果字符串。

原始回溯

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_entry 是一个 raw_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

使用给定的 raw_backtrace 重新引发异常,作为异常来源。

当前调用堆栈

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 的构造函数的内部名称。