Erlang 异常

在任何编程语言中,都需要异常处理来处理运行时错误,这样才能保持应用程序的正常流。异常通常会中断应用程序的正常流,这就是为什么我们需要在应用程序中使用异常处理的原因。

通常,当Erlang中发生异常或错误时,将显示以下消息。

{"init terminating in do_boot", {undef,[{helloworld,start,[],[]}, 
{init,start_it,1,[]},{init,start_em,1,[]}]}}

故障转储将被写入-

erl_crash.dump
init terminating in do_boot ()

在Erlang中,有3种例外类型-

  • Error?调用将终止当前进程的执行,并在捕获到最后一个函数及其参数时包含堆栈跟踪。这些是引发上述运行时错误的异常。erlang:error(Reason)

  • Exists ?有两种Exists : 内部退出和外部退出。内部退出通过调用函数 exit/1来触发,并使当前进程停止执行。外部出口在 exit/2中被调用,并且与 Erlang 的并发方面中的多个进程有关。

  • Throw ?throw是一类异常,用于程序员可以处理的情况。与退出和错误相比,它们并没有带来任何“崩溃过程!”他们背后的意图,而是他们控制的流量。当您在期望程序员处理抛出时使用抛出,通常最好在使用它们的模块中记录它们的使用。

try... catch 是一种计算表达式的方法,同时让您处理成功的案例以及遇到的错误。

try-catch表达式的一般语法如下所示。

语法

try Expression of 
SuccessfulPattern1 [Guards] -> 
Expression1; 
SuccessfulPattern2 [Guards] -> 
Expression2 

catch TypeOfError:ExceptionPattern1 -> 
Expression3; 
TypeOfError:ExceptionPattern2 -> 
Expression4 
end

在 try 和 of 之间的表达式被称为是受保护的。这意味着该调用中发生的任何类型的异常都将被捕获。在 try... 和 catch 之间的模式和表达式与 case... 的行为方式完全相同。

Finally,catch 部分——在这里,您可以为本章中看到的每种类型,用 error、 throw 或 exit 替换 TypeOfError。如果没有提供类型,则假定抛出。

Error错误类型
badarg

参数的数据类型错误,或者格式不正确。

badarith

算术表达式中的错误参数。

{badmatch,V}

匹配表达式的求值失败。值V不匹配。

function_clause评估函数调用时找不到匹配的函数子句。
{case_clause,V}

计算case表达式时找不到匹配的分支。值V不匹配。

if_clause评估if表达式时,找不到真正的分支。
{try_clause,V}

计算try表达式的节的时找不到匹配的分支。值V不匹配。

undef评估函数调用时找不到该函数。
{badfun,F}有趣的F出了点问题
{badarit,F}

一个趣味被应用于错误数量的参数。F描述了其中的乐趣和争论。

timeout_valuereceive..after表达式中的超时值将计算为除整数或无穷大之外的其他值。
noproc尝试链接到不存在的进程。

以下是如何使用这些异常以及如何进行处理的示例。

  • 第一个函数生成所有可能的异常类型。

  • 然后我们编写一个包装器函数,在try…catch表达式中调用generate_exception。

在线示例

-module(helloworld). 
-compile(export_all). 

generate_exception(1) -> a; 
generate_exception(2) -> throw(a); 
generate_exception(3) -> exit(a); 
generate_exception(4) -> {'EXIT', a}; 
generate_exception(5) -> erlang:error(a). 

demo1() -> 
   [catcher(I) || I <- [1,2,3,4,5]]. 
catcher(N) -> 
   try generate_exception(N) of 
      Val -> {N, normal, Val} 
   catch 
      throw:X -> {N, caught, thrown, X}; 
      exit:X -> {N, caught, exited, X}; 
      error:X -> {N, caught, error, X} 
   end. 
      
demo2() -> 
   [{I, (catch generate_exception(I))} || I <- [1,2,3,4,5]]. 
demo3() -> 
   try generate_exception(5) 
   catch 
      error:X -> 
         {X, erlang:get_stacktrace()} 
   end. 
   
lookup(N) -> 
   case(N) of 
      1 -> {'EXIT', a}; 
      2 -> exit(a) 
   end.

如果我们运行程序的HelloWorld::demo().,我们将获得以下输出

[{1,normal,a},
{2,caught,thrown,a},
{3,caught,exited,a},
{4,normal,{'EXIT',a}},
{5,caught,error,a}]