查看源码 错误和错误处理

术语

错误大致可以分为四种类型

  • 编译时错误 - 当编译器无法编译程序时,例如语法错误。

  • 逻辑错误 - 当程序没有按预期运行,但没有崩溃时。一个例子是点击图形用户界面中的按钮时没有任何反应。

  • 运行时错误 - 当发生崩溃时。一个例子是将运算符应用于错误类型的参数。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 - 元组的第二个元素是一个映射,提供有关导致异常原因的附加信息。此信息可以通过调用 error/3 来创建,并由 erl_error:format_exception/4 使用。

  • file - 元组的第二个元素是一个字符串(字符列表),表示函数源文件的文件名。

  • line - 元组的第二个元素是发生异常或调用函数的源文件中的行号(整数 > 0)。

警告

开发人员应仅将堆栈跟踪条目用于调试目的。

虚拟机执行尾调用优化,这不会向堆栈跟踪添加新条目,并且还将堆栈跟踪限制为一定的深度。此外,编译器选项、优化和未来的更改可能会添加或删除堆栈跟踪条目,从而导致任何期望堆栈跟踪以特定顺序或包含特定项的代码失败。

此规则的唯一例外是具有原因 undeferror 类,它保证将尝试的函数的 ModuleFunctionArity 作为第一个堆栈跟踪条目。

在 Erlang 中处理运行时错误

进程内的错误处理

可以通过使用 trycatch 来防止运行时错误和其他异常导致进程终止。

进程之间的错误处理

进程可以监视其他进程并检测进程终止,请参阅进程

退出原因

当发生运行时错误时,即 error 类的异常。退出原因是元组 {Reason,Stack},其中 Reason 是一个表示错误类型的术语

  • 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 - 尝试创建指向不存在的进程或端口的 linkmonitor

  • noconnection - 由于无法建立节点之间的连接或连接已断开,因此与远程进程的链接或监视中断。

  • {nocatch,V} - 尝试在 catch 外部评估 throwV 是抛出的术语。

  • system_limit - 已达到系统限制。有关系统限制的信息,请参阅效率指南中的系统限制

Stack 是发生错误时正在计算的函数调用堆栈,以元组 {Module,Name,Arity,ExtraInfo} 的列表形式给出,最近的函数调用在前。在某些情况下,最近的函数调用元组可以是 {Module,Name,[Arg],ExtraInfo}