在Erlang编程中,报错是一个常见的现象,了解这些错误类型和处理方法对于开发健壮的Erlang应用程序至关重要,本文将详细介绍Erlang中的常见报错类型、异常处理机制以及一些实际案例分析,帮助开发者更好地理解和解决这些问题。
Erlang中的常见报错类型
1、编译错误:主要是编译器检测出的代码语法错误,变量未定义、模块名拼写错误等。

2、逻辑错误:程序没有完成预期的工作,通常是由于算法或逻辑设计上的问题。
3、运行时错误:Erlang运行时抛出的错误,如对非数据类型执行算术运算,或者函数调用时参数不匹配。
4、用户代码生成的错误:通过exit/1
或throw/1
函数生成的错误。
5、模式匹配错误:最常见的例子是给一个变量赋不同的值,导致匹配失败。
6、函数子句错误:函数已定义,但找不到匹配的函数子句。
7、case表达式错误:case表达式找不到匹配的分支。

8、if表达式错误:if表达式要求最少有一个分支测试条件的结果为true,否则会引发错误。
9、未定义错误:调用未定义的函数或模块。
10、进程不存在错误:如gen_server call一个不存在的进程。
11、系统限制错误:超出系统上限,如atom, ets, port, process等。
异常处理机制
Erlang提供了三种主要的异常类型:throw、error和exit。
1、throw型异常:用于抛出一个调用者可能会捕获的异常,针对throw,必须为函数添加注释,说明它会抛出这个异常,调用者可以选择忽略这些异常或对异常进行处理。

2、error型异常:通过erlang:error/1
或erlang:error/2
生成,用于抛出那些“崩溃错误”,这种异常应该是调用者不会真正意识到要去处理的那些致命错误。
3、exit型异常:通过exit/1
生成,当想要终止当前进程时,用这个函数,如果这个消息未被捕获,那么系统会向所有与当前进程连接的进程广播{'EXIT', PID, Reason}消息。
异常的捕获
在Erlang中,进程内的异常可以通过try, catch来进行捕获处理,推荐使用try,其为新添加的语法,进程间的异常可以通过监督树(supervisor tree),监控进程(monitor)来实现。
- try
- Exprs
- catch
- Class:Reason >
- %% 异常处理代码
- %% Class为异常类型,Reason为异常原因
- ok
- end.
- try
- whatever
- catch
- Class:Reason >
- io:format("Class: ~p, Reason: ~p~nstacktrace: ~p", [Class, Reason, erlang:get_stacktrace()]),
- error
- end.
实际案例分析
1、badarg错误:参数类型错误,传入参数和函数要求参数不匹配,把atom作为参数传给erlang:integer_to_list/1
。
- erlang:integer_to_list(a).
- ** exception error: bad argument
- in function integer_to_list/1 (test.erl, line 4)
2、badarith错误:算实运算错误,如一个整数和atom相加。
- 10 + c.
- ** exception error: an error occurred when evaluating an arithmetic expression
- in operator +/2 (<stdin> line 1)
3、function_clause错误:函数已定义,但找不到匹配的函数子句。
- module(test).
- export([add/2]).
- add(A, B) when is_integer(A), is_integer(B) > A + B.
- erl
- 1> test:add(10, 1).
- 11
- 2> test:add(10, 1.0).
- ** exception error: no function clause matching test:add(10, 1.0) (test.erl, line 4)
4、case_clause错误:case表达式找不到匹配的分支。
- Val = 0,
- case Val of
- 1 > lt;
- 2 > gt
- end.
- ** exception error: no case clause matching 0
FAQs
Q1: 如何在Erlang中捕获和处理异常?
A1: 在Erlang中,可以使用try, catch
块来捕获和处理异常。try
块中包含可能会引发异常的代码,而catch
块则定义了如何处理这些异常。
- try
- whatever
- catch
- Class:Reason >
- io:format("Class: ~p, Reason: ~p~nstacktrace: ~p", [Class, Reason, erlang:get_stacktrace()]),
- error
- end.
Q2: Erlang中的三种主要异常类型是什么?
A2: Erlang中的三种主要异常类型是throw、error和exit,throw用于抛出调用者可能会捕获的异常;error用于抛出那些“崩溃错误”,通常是致命错误;exit用于终止当前进程,并向所有与当前进程连接的进程广播{'EXIT', Pid, Reason}消息。