• [erlang 001] erlang中的错误及异常处理


    一、 erlang中的错误

    1. 分类

        1) 编译错误:主要是编译器检测出的代码语法错误;

        2) 逻辑错误:是指程序没有完成预期的工作,属于开发人员的问题;

        3) 运行时错误:是指erlang运行时抛出的错误,比如对非数据类型执行算术运算,erlang运行时会捕获异常,并抛出。在erlang中,这类异常的类型为error;

        4) 用户代码生成的错误:是指通过exit/1或者throw/1生成。

    2. 异常

    我们把运行时错误以及用户抛出的错误称为异常(exception),他们具有三种类型:throw, error, exit。

        1) error型异常,通过erlang:error/1, 2生成,用于抛出那些“崩溃错误”。这种异常应该是调用者不会真正意识到要去处理的那些致命错误;

        2) throw型异常,通过throw/1生成,用于抛出一个调用者可能会捕获的异常。针对throw,必须为函数添加注释,说明他会抛出这个异常。调用者可以选择:忽略这些异常/对异常进行处理;

        3) exit型异常,通过exit/1生成,当想要终止当前进程时,用这个函数。如果这个消息未被捕获,那么系统会向所有与当前进程连接的进程广播{'EXIT',Pid,Reason}消息

    3. 异常的捕获

    在erlang中,进程内的异常可以通过try, catch来进行捕获处理。

    推荐使用try,其为新添加的语法。进程间的异常可以通过监督树(supervisor tree),监控进程(monitor)来实现。

    如果是通过catch捕捉这三种异常,则返回的结果分别是:

    • throw(Any) -> Term
    • exit(Reason) -> {'EXIT',Reason}
    • error(Reason) -> {'EXIT',{Reason,erlang:get_stacktrace()}}

    4. 一些场景的报错类型

    badarg:参数错误,参数格式或类型错误

    badarith:算术表达式错误,算术表达式中含有错误的参数

    {badmatch,V}:模式匹配错误,V指具体的发生匹配错误的数值

    function_clause:函数子句错误,没有找到匹配的函数子句

    {case_clause,V}:case匹配错误,没有找到匹配的case pattern

    if_clause:if子句错误,没有找到为ture的if子句

    {try_clause,V}:try匹配错误,执行try时,没有找到匹配的pattern

    undef:函数未定义错误

    {badfun,F}:函数错误

    {badarity,F}:函数参数个数错误

    timeout_value:超时参数错误,在receive.. after语法中,after对应的超时数据错误(应为不小于0的integer或infinity

    noproc:Process 错误,Process不存在

    {nocatch,V}:throw未被catch

    system_limit:系统限制错误,某些性能或数据达到系统极限

    二、try…catch语法

    1. 语法

    try FuncOrExpressionSeq of 
        Pattern1 [when Guard1] -> Expressions1;
        Pattern2 [when Guard2] -> Expressions2;
        ...
    catch 
        ExceptionType1: ExPattern1 [when ExGuard1] -> ExExpressions1;
        ExceptionType2: ExPattern2 [when ExGuard2] -> ExExpressions2;
        ...
    after
        AfterExpressions
    end

    返回值:try表达式具有一个值;如果try FuncOrExpressionSeq后没有of部分,则默认为FuncOrExpressionSeq的返回值;

    异常处理语句发生异常:如果在of部分或者catch部分,发生了异常,那么异常将不被处理,直接抛出;

    catch语句块的ExceptionType1前内容省略的话,默认的错误标签是throw

    after部分:after之后的代码是用来在FuncOrExpressionSeq结束后执行清理的,这段代码一定会被执行。并且FuncOrExpressionSeq的返回值会被丢弃。

    2. 测试代码

    代码部分:

    -module(test_try).  
    -compile([export_all]).  
    -author('cheng litaocheng@gmail.com').  
    %% @spec test(F1, F2) -> Result  
    %% @doc evaluate the F , use the try to catch all kinds of error  
    %%  F1 the Expression to be catch exception  
    %%  F2 the Expression evaluate in the catch section  
    test(F1, F2) when (is_function(F1, 0) andalso is_function(F2, 0)) ->  
        try F1()  
        catch  
            throw:X ->  
                {{caught, throw, X}, F2()};  
            exit:X ->  
                {{caught, exit, X}, F2()};  
            error:X ->  
                {{caught, error, X}, F2()}  
        after  
            io:format("always evaluate the after body~n")  
        end.

    测试结果:

    21> c(test_try).  
    {ok,test_try}  
    
    22> test_try:test(fun() -> throw(hello) end, fun() -> ok end).  
    always evaluate the after body  
    {{caught,throw,hello},ok}  
    
    23> test_try:test(fun() -> exit(hello) end, fun() -> ok end).  
    always evaluate the after body  
    {{caught,exit,hello},ok}  
    
    24> test_try:test(fun() -> erlang:error(hello) end, fun() -> ok end).  
    always evaluate the after body  
    {{caught,error,hello},ok}  
    
    25> test_try:test(fun() -> erlang:error(hello) end, fun() -> throw(exception_in_catch) end).  
    always evaluate the after body  
    ** exception throw: exception_in_catch  
    in function test_try:test/2

    参考及整理自:

    [1] http://erlangdisplay.iteye.com/blog/315417 

    [2] http://blog.sina.com.cn/s/blog_53a5047b01018wp5.html

  • 相关阅读:
    快速入门 ASP.NET MVC
    关于ASP.NET中由于无法创建应用程序域,因此未能执行请求解决方案
    Microsoft ASP.NET MVC Beta IIS6 部署
    弹窗显示正在执行的任务
    多线程加深理解_进攻五个城
    反射与配置文件简单使用
    C#中MemberwiseClone的理解
    C# App.config 自定义 配置节 报错“配置系统未能初始化” 解决方法
    多线程信号源的理解
    日志的记录
  • 原文地址:https://www.cnblogs.com/harrymore/p/4402702.html
Copyright © 2020-2023  润新知