`
mryufeng
  • 浏览: 982709 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

对try 异常 运行的疑问,为什么出现两种结果

阅读更多
郎咸武<langxianzhe@163.com>  同学在erlang-china上post了一个问题:
请注意编号为91和92两行运行结果,请问为什么会出现两种结果。
一个抛出 {error,{badmatch,5}}
另一个抛出** exception error: no match of right hand side value 4
view source
print?
01 root@ubuntu:/usr/src/otp# erl
02 Erlang R13B04 (erts-5.7.5) [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false
03 88> X=1.
04 1
05 89> try (X=5) of Val ->{normal,Val} catch error:Error -> {error,Error}  end.
06 {error,{badmatch,5}}
07 90> try (X=1) of Val ->{normal,Val} catch error:Error -> {error,Error}  end.
08 {normal,1}
09 91> try (X=5) of Val ->{normal,Val} catch error:Error -> {error,Error}  end.
10 {error,{badmatch,5}}
11 92> try (X=4) of Val ->{normal,Val} catch error:Error -> {error,Error}  end.
12 ** exception error: no match of right hand side value 4
13 93> self().
14 <0.36.0>
15 94> catch try (X=4) of Val  ->{normal,Val} catch error:Error -> {error,Error}  end. %%这个异常是 shell捕获到了 进一步处理后的结果
16 {'EXIT',{{badmatch,4},[{erl_eval,expr,3}]}}
17 95> try (X=4) of Val ->{normal,Val} catch error:Error ->  {error,Error}  end.
18 ** exception error: no match of right hand  side value 4
19 96> self().
20 <0.36.0>

竟然是EXIT, 这时候shell也换了pid了, 这是怎么回事呢?
由于在shell输入的程序是公司允许的, 我们也可以从出错的stack里面看到是 erl_eval:expr函数异常了.
现在让我们对系统打patch如下:
lib/stdlib/src/erl_eval.erl
view source
print?
1 282expr({match,_,Lhs,Rhs0},  Bs0, Lf, Ef, RBs) ->
2 283    {value,Rhs,Bs1} = expr(Rhs0, Bs0,  Lf, Ef, none),
3 284    case match(Lhs, Rhs, Bs1) of
4 285         {match,Bs} ->
5 286            ret_expr(Rhs, Bs, RBs);
6 287        nomatch ->
7 288            io:format("expr nomatch->pid:~p~n~p~n",[self(), Rhs]),   %%添加诊断
8 289             erlang:raise(error, {badmatch,Rhs}, stacktrace())
9 290    end;

erts/emulator/beam/bif.c
view source
print?
01 1142/**********************************************************************/
02 1143/*  raise an exception of given class, value and  stacktrace.
03 1144  *
04 1145 * If there is an error in the argument  format,
05 1146 * return the atom 'badarg'  instead.
06 1147 */
07 1148Eterm
08 1149raise_3(Process *c_p, Eterm class,  Eterm value, Eterm stacktrace) {
09 ...
10 1222     erts_print(ERTS_PRINT_STDOUT, NULL, "raise->proc:%T\nclass=%T\nvalue=%T\nstacktrace=%T\n", c_p->id, class, value,  c_p->ftrace); /*添加诊断*/
11 1223    BIF_ERROR(c_p, reason);
12 ...
13 }

然 后我们在运行上面的语句:
view source
print?
01 root@ubuntu:~/otp#  bin/erl
02 Erlang R13B04 (erts-5.7.5) [source]  [smp:2:2] [rq:2]  [async-threads:0] [kernel-poll:false]
03
04 Eshell  V5.7.5  (abort with  ^G)
05 1> X=1.
06 1
07 2>  try (X=5) of Val ->{normal,Val}  catch error:Error ->  {error,Error}  end.
08 expr nomatch->pid:<0.32.0>
09 5
10 raise->proc:<0.32.0>
11 class=error
12 value={badmatch,5}
13 stacktrace=[[{erl_eval,expr,3}
14 {error,{badmatch,5}}
15 3>  try  (X=4) of Val ->{normal,Val} catch  error:Error -> {error,Error}   end.
16 expr nomatch->pid:<0.32.0>
17 4
18 raise->proc:<0.32.0>
19 class=error
20 value={badmatch,4}
21 stacktrace=[[{erl_eval,expr,3}]|-000000000000000016]
22 raise->proc:<0.32.0>
23 class=error
24 value={badmatch,4}
25 stacktrace=[[{erl_eval,expr,3}]|-000000000000000016]

很奇怪的是第3句raise了2次. 让我们回到程序好好看下:
view source
print?
1 X=1.   %%这行绑定了一个变量X=1
2 try (X=5) of Val ->{normal,Val} catch  error:Error -> {error,Error}  end.   %%这行由于异常会试图绑定变量Error={badmatch,5}, 由于之前Error不存在, 绑定成功.
3 try  (X=4) of Val ->{normal,Val} catch error:Error -> {error,Error}   end.   %%这行由于异常会绑定了变量Error={badmatch,4}, 由于Error存在,  而且值是{badmatch,5},所以这时候catch就出
4 现异常了,  往外抛出{'EXIT',{{badmatch,4},[{erl_eval,expr,3}]}}.

这 下我们明白了, 是这个catch惹的祸了.
我们再实验下我们的分析:
view source
print?
01 root@ubuntu:~#  erl
02 Erlang R13B04 (erts-5.7.5) [source] [smp:2:2] [rq:2]  [async-threads:0] [hipe] [kernel-poll:false]
03
04 Eshell V5.7.5   (abort with ^G)
05 1> X=1.
06 1
07 2> b().
08 X = 1
09 ok
10 3>  try (X=5) of Val ->{normal,Val} catch error:Error ->  {error,Error}  end.
11 {error,{badmatch,5}}
12 4> b().
13 Error =  {badmatch,5}
14 X = 1
15 ok
16 5> try (X=4) of Val ->{normal,Val}  catch error:Error -> {error,Error}  end.
17 ** exception error: no  match of right hand side value 4
18 6> f(Error).
19 ok
20 7>  b().
21 X = 1
22 ok
23 8> try (X=4) of Val ->{normal,Val}  catch error:Error -> {error,Error}  end.
24 {error,{badmatch,4}}
25 9>

Bingo成功.
结论: 要非常小心Erlang语法的变量绑定,在不同的路线会有不同的绑定,容易出问题.
1
0
分享到:
评论

相关推荐

    try_catch效率

    通过对比两种情况下的时间差异,可以得出`try-catch`对系统效率的具体影响程度。 在实际的项目开发中,优化性能时,我们应当权衡异常处理的必要性和潜在的性能损失。对于那些不期望抛出异常的代码,或者性能至关...

    java异常课件

    异常分为两种类型:检查性异常(Checked Exceptions)和运行时异常(Runtime Exceptions)。检查性异常是编译时需要处理的,如`IOException`,而运行时异常则是在程序运行过程中才可能出现,如`NullPointerException...

    Java_解惑(PDF)

    初学者可能会对try-catch-finally块的使用,以及如何自定义异常有所疑问。 4. **数组与集合**:Java提供了数组和多种集合框架,如ArrayList、LinkedList、HashMap等。PDF可能包含如何操作数组,以及何时使用不同...

    Java解惑 中文版

    书中会讲解如何运用这两种特性来增强代码的灵活性和可维护性。 7. **JVM优化**:理解JVM的工作原理对提升程序性能至关重要。读者将学习如何分析和调整JVM参数,实现应用程序的最优运行。 8. **Java健壮程序**:这...

    Abap基础学习文档2_ABAP4程序语法和格式.doc

    - **子例程**:包括过程(PROCEDURE)和形式(FORM)两种类型。 - **过程**:可以带返回值。 - **形式**:主要用于执行特定任务,不返回值。 #### 五、异常处理 - **定义异常**:通过`CLASS lcl_abap_exception ...

    零点起飞学C#随书源代码

    8. **Windows Forms和WPF**:如果你打算开发桌面应用,C#可以结合这两种UI框架创建图形用户界面。 9. **ASP.NET**:对于Web开发,C#与ASP.NET结合,可以创建动态网站和服务。 在"源文件"目录中,你将找到书中各个...

    j6se中文帮助文档(chm)

    12. **异常处理**:Java的异常处理机制使得程序在遇到错误时能够优雅地恢复,文档会介绍如何使用try-catch-finally和throw捕获和处理异常。 通过深入学习这个"j6se中文帮助文档(chm)",开发者不仅可以掌握Java 6...

    C# 论坛C# 论坛

    3. **异常处理**:通过try-catch-finally结构,C#提供了强大的错误处理机制,帮助开发者捕获和处理程序运行时可能出现的异常情况。 4. **LINQ(Language Integrated Query)**:这是C#中的一个特性,允许开发者使用...

    java编程软件

    3. **异常处理**:Java使用try-catch-finally结构来处理运行时错误,增强了程序的健壮性。 4. **集合框架**:ArrayList、LinkedList、HashSet、HashMap等容器类是Java编程中不可或缺的部分,它们用于存储和操作数据...

    java 编程 经典案例集锦

    3. **异常处理**:Java的异常处理机制是其特色之一,案例可能会展示如何使用try-catch-finally语句块来捕获和处理程序运行时可能出现的错误。 4. **数组与集合**:Java提供了丰富的数据结构,如数组、ArrayList、...

    Coin-Project

    8. **异常处理**:在处理用户输入时,可能会遇到无效的数据,因此需要使用try-catch块进行异常处理,确保程序的稳定运行。 9. **多线程**:如果程序需要同时模拟多个硬币的投掷,可以使用`Thread`类或`...

    框架用法实例vb2008应用程序

    3. **异常处理**:VB.NET支持Try-Catch-Finally语句块进行异常处理,这使得程序在遇到错误时能够更优雅地恢复或提示用户。 4. **多线程**:System.Threading命名空间提供了对多线程的支持,开发者可以创建并控制多...

    java语言程序设计课件最新版的

    1. **Java语言基础**:Java是一种面向对象的、跨平台的编程语言,由Sun Microsystems(现为Oracle Corporation)在1995年发布。它的设计目标是具有简单性、面向对象、健壮性、安全性、可移植性等特性。课件中可能会...

    小黑课堂计算机二级Python题库3.4.zip

    3. **异常处理**:学习如何使用try/except块来捕获和处理程序运行时可能出现的错误,以增强程序的健壮性。 4. **面向对象编程**:理解类的概念,包括类的定义、实例化、封装、继承和多态。掌握构造函数(`__init__`...

    C#实现百分比转小数的方法

    首先,需要明确百分比字符串的两种常见形式:一种是不带百分号的纯数值形式,另一种是带有百分号的完整百分比形式。无论哪种形式,其核心转换逻辑是相同的,即将百分比数值除以100,从而得到小数形式的表示。 在C#...

    為 CSDN-CSDN社区-C/C++-新手乐园 的朋友所回答的第二問題。

    9. **异常处理**:C++引入了异常处理机制(try-catch),用于捕获运行时错误,而C语言通常依赖于返回值和错误代码。 10. **标准库**:C++的标准库(STL)提供了容器(如vector、list、set等)、算法、迭代器和函数...

    PHP新手上路中文教程(推荐)

    1. **MySQLi**:MySQL Improved Extension,适用于较旧的MySQL数据库,提供面向对象和面向过程两种接口。 2. **PDO (PHP Data Objects)**:为多种数据库提供统一的接口,支持预处理语句,提高安全性。 3. **SQL...

    Kotlin文档

    - **互操作性**:Kotlin与Java完全兼容,因此可以在同一项目中混合使用这两种语言。 - **简洁性**:Kotlin的语法更加简洁,能够减少代码量,提高开发效率。 - **安全性**:Kotlin内置了空安全特性,减少了运行时...

Global site tag (gtag.js) - Google Analytics