对try 异常 运行的疑问,为什么出现两种结果
来源:互联网 发布:电力调度电话交换网络 编辑:程序博客网 时间:2024/05/22 04:43
ErlangUbuntuCC++C#.
郎咸武<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语法的变量绑定,在不同的路线会有不同的绑定,容易出问题.
- 对try 异常 运行的疑问,为什么出现两种结果
- Python异常(try...except)对代码运行性能的影响
- 对两种web开发中经常出现的异常问题的总结(NoClassDefFound,ClassNotFound)
- vc为什么会出现输出结果为0的情况(异常分析)
- try...catch...finally的疑问
- try catch finally里面出现return时候的结果
- 对异常处理中的一个问题的思考(出现异常,程序仍能继续运行)
- OJ上判题时出现的运行结果整理
- 浅谈为什么java命令运行class文件出现异常
- 私有继承对try catch异常抛出的影响
- java中对异常的捕获(try,catch,finally)
- try catch 对代码运行的性能影响
- 关于try{....return;}finally{....}的疑问
- 对SharpMap的疑问
- 异常:编译时异常和运行时异常&throw和throws区别try-catch的应用
- 为什么运行不出结果?
- 为什么运行结果老是错误
- 异常捕捉先后顺序------getCustomerInfo()方法如下,try中可以捕获三种类型的异常,如果在该方法运行中产生了一个IOException,将会输出什么结果()
- 内连接与外连接
- 郑愁予-《美丽的错误》
- libsvm所用数据格式
- e-人事管理系统-人事档案-变更管理-人员合同变更
- 不规则物体形状匹配综述
- 对try 异常 运行的疑问,为什么出现两种结果
- 析构函数为虚函数
- myeclipse导入现有项目出错
- 基于Redis的CAS集群
- iptables 指南
- UVa 10192 - Vacation(LCS水题)
- A. Room Leader
- Memory matters - even in Erlang (再次说明了了解内存如何工作的必要性)
- 利用mkimage 把zImage转换为uImage的方法