📜  Erlang-异常

📅  最后修改于: 2020-11-04 05:55:15             🧑  作者: Mango


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

通常,当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种例外类型-

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

  • 存在-存在两种出口:“内部”出口和“外部”出口。通过调用函数exit / 1触发内部出口,并使当前进程停止其执行。外部出口用exit / 2调用,并且在Erlang的并发方面必须处理多个进程。

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

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

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

句法

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

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

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

最后,抓住部分–在这里,对于本章中我们所见过的每种类型,都可以用错误,抛出或退出来替换TypeOfError 。如果没有提供类型,则假定抛出。

以下是Erlang中的一些错误和错误原因-

Error Type of Error
badarg Bad argument. The argument is of wrong data type, or is otherwise badly formed.
badarith Bad argument in an arithmetic expression.
{badmatch,V} Evaluation of a match expression failed. The value V did not match.
function_clause No matching function clause is found when evaluating a function call.
{case_clause,V} No matching branch is found when evaluating a case expression. The value V did not match.
if_clause No true branch is found when evaluating an if expression.
{try_clause,V} No matching branch is found when evaluating the of-section of a try expression. The value V did not match.
undef The function cannot be found when evaluating a function call..
{badfun,F} Something is wrong with a fun F
{badarity,F} A fun is applied to the wrong number of arguments. F describes the fun and the arguments.
timeout_value The timeout value in a receive..after expression is evaluated to something else than an integer or infinity.
noproc Trying to link to a non-existing process.

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

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

  • 然后,我们编写一个包装函数,以在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  
   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  
   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}]