MATLAB try-catch Block
Introduction
在MATLAB中,try-catch块1:
1
2
3
4
5
try
statements
catch exception
statements
end
将执行在try block中的语句,并且在catch block中捕捉可能发生的错误。我们可以通过这种方式重载(override)程序语句的默认错误行为(中断程序)。如果try block中的语句产生了错误,那么程序会自动跳转到包含着用户自定义错误处理语句的catch block中,我们可以在catch block中为特定错误添加错误信息、将错误转换为警告以防止程序中断、甚至忽略掉特定错误等等。
Example 1: Supplement Error Message
正常情况下,MATLAB中的语句:
1
2
3
4
5
6
clc, clear, close all
A = rand(3);
B = ones(5);
C = [A; B];
会出现下面的报错信息:
1
2
3
4
5
Error using vertcat
Dimensions of arrays being concatenated are not consistent.
Error in script1 (line 6)
C = [A; B];
如果我们将C = [A; B];放入到下面简单的try-catch块中:
1
2
3
4
try
C = [A; B];
catch ME
end
运行后可以看到此时的命令行窗口中并不会产生报错信息,而是会在工作空间中产生一个ME变量,该变量是一个MException对象,其中包含着一些报错信息:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
>> ME
ME =
MException with properties:
identifier: 'MATLAB:catenate:dimensionMismatch'
message: 'Dimensions of arrays being concatenated are not consistent.'
cause: {}
stack: [1×1 struct]
Correction: []
>> ME.stack
ans =
struct with fields:
file: 'C:\Users\Tsing\Desktop\gramming\errors\script2.m'
name: 'script2'
line: 7
如果我们想要像之前一样在命令行窗口中抛出错误,则可以使用rethrow函数:
注:也可以使用throw函数,rethrow函数和throw函数是有一些区别的,具体可以参考2。
1
2
3
4
5
6
...
try
C = [A; B];
catch ME
rethrow(ME)
end

虽然报错信息是一样的,但是此时的变量空间中多出了ME这个变量。
另外需要说明的是,
ME是我们自己定义的变量名,我们可以通过改变catch后的变量名来改变这一点,例如:
1 2 3 4 5 6 ... try C = [A; B]; catch me rethrow(me) end
根据变量ME中包含的错误信息,我们可以通过catch block中的程序来丰富报错信息,例如:
1
2
3
4
5
6
7
8
9
10
11
12
13
...
try
C = [A; B];
catch ME
if (strcmp(ME.identifier, 'MATLAB:catenate:dimensionMismatch'))
msg = ['Dimension mismatch occurred: First argument has ', ...
num2str(size(A,2)),' columns while second has ', ...
num2str(size(B,2)),' columns.'];
causeException = MException('MATLAB:myCode:dimensions', msg);
ME1 = addCause(ME, causeException);
end
rethrow(ME1)
end
此时命令行中的报错信息就多了关于维度的更详细的报错信息:

最后,我们可以简单对比一下添加信息前后的两个MExpection对象ME和ME1:
1
2
3
4
5
6
7
8
ME =
MException with properties:
identifier: 'MATLAB:catenate:dimensionMismatch'
message: 'Dimensions of arrays being concatenated are not consistent.'
cause: {}
stack: [1×1 struct]
Correction: []
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ME1 =
MException with properties:
identifier: 'MATLAB:catenate:dimensionMismatch'
message: 'Dimensions of arrays being concatenated are not consistent.'
cause: {[1×1 MException]}
stack: [1×1 struct]
Correction: []
ME1.cause{1} =
MException with properties:
identifier: 'MATLAB:myCode:dimensions'
message: 'Dimension mismatch occurred: First argument has 3 columns while second has 5 columns.'
cause: {}
stack: [0×1 struct]
Correction: []
Example 2: Repackage Error as Warning
try-catch块可以用来将错误repackage为warning。例如在正常情况下,当我们调用一个没有定义的函数notaFunction,软件会报错:
1
a = notaFunction(5,6);

我们可以将这个错误repackage为warning:
1
2
3
4
5
6
try
a = notaFunction(5,6);
catch
warning('Problem using function. Assigning a value of 0.');
a = 0;
end

甚至我们可以更激进一点,将整个错误都隐藏掉:
1
2
3
4
try
a = notaFunction(5,6);
catch
end
此时的工作空间中没有一个变量。
Example 3: Handle Different Types of Errors
try-catch代码块中catch后的exception变量是一个MException对象,我们可以通过它来识别错误。因此,我们可以使用try-catch以不同的方式处理不同类型的错误。例如还是针对上面的例子,我们想要实现:
- If the function
notaFunctionis undefined, issue a warning instead of an error and assign the output a value ofNaN. - If
notaFunction.mexists, but is a script instead of a function, issue a warning instead of an error, run the script, and assign the output a value of0. - If MATLAB throws an error for any other reason, rethrow the exception.
则可以使用代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
try
a = notaFunction(5,6);
catch ME
switch ME.identifier
case 'MATLAB:UndefinedFunction'
warning('Function is undefined. Assigning a value of NaN.');
a = NaN;
case 'MATLAB:scriptNotAFunction'
warning(['Attempting to execute script as function. '...
'Running script and assigning output a value of 0.']);
notaFunction;
a = 0;
otherwise
rethrow(ME)
end
end
这意味着我们将前面两种错误视为不同的warnings,并赋给变量a不同的值(供后续程序使用),而不处理其他错误的报错信息和行为。开发者可以通过这种方式设计程序遇到预期错误时的行为,给出警告并做出响应(最简单的就像是上面给变量a赋不同值的操作),而不需要中断整个程序;程序只有遇到非预期错误时才会中断。
Example 4: When There Exist No Mistakes
当语句不存在错误时,try-catch是捕捉不到任何错误的,并且不会执行catch块中的内容。例如运行代码:
1
2
3
4
5
6
7
8
9
a = 1;
b = 2;
try
c = a+b;
catch ME
d = 2;
rethrow(ME)
end
此时:
- 工作空间中仅存在变量
a,b,和c,不存在变量ME和d; - 程序不会报错;
这也很容易理解,这个块是用来尝试(try)捕捉(catch)错误的,如果代码片段没有错误,当然捕捉不到也不会报错。
References