对异常作出响应
概述
默认情况下,当抛出异常时,MATLAB® 软件会终止当前正在运行的程序。但如果您捕获到程序中的异常,则可以捕获有关出现的问题的信息,并以适合特定条件的方式处理该情况。这需要使用 try/catch 语句。
try/catch 语句
当您的代码中包含会生成不需要的结果的语句时,请将这些语句放入 try/catch 块中,以捕获任何错误并对这些错误进行适当处理。
try/catch 语句类似于下面的伪代码。它包括两部分:
try块,其中包含try和catch语句之间的所有行。catch块,其中包含catch和end语句之间的所有代码行。
try
Perform one ...
or more operations
A catch ME
Examine error info in exception object ME
Attempt to figure out what went wrong
Either attempt to recover, or clean up and abort
end
B Program continues
程序将执行 try 块中的语句。如果程序遇到错误,则会跳过 try 块中其余的任何语句并跳转到 catch 块的开头(此处显示为点 A)。如果 try 块中的所有操作均成功,则执行过程会完全跳过 catch 块并转至 end 语句后面的第一行(点 B)。
建议在不同的行上指定 try、catch 和 end 命令以及 try 和 catch 块的代码。如果您将这其中的任何部分合并在同一行上,请用逗号加以分隔:
try, surf, catch ME, ME.stack, end
ans =
file: 'matlabroot\toolbox\matlab\graph3d\surf.m'
name: 'surf'
line: 49注意
您不能在 try 或 catch 块中定义嵌套函数。
Try 块
执行时,您的代码进入 try 块并执行每个语句,就好像它是正规程序的一部分一样。如果未遇到任何错误,MATLAB 会完全跳过 catch 块并在 end 语句后继续执行。如果其中任何 try 语句失败,MATLAB 会立即退出 try 块,且不执行该块中的任何其余语句,并进入 catch 块。
Catch 块
catch 命令标记 catch 块的开头,并提供对包含导致异常的信息的数据结构体的访问。这在前面的伪代码中显示为变量 ME。ME 是一个 MException 对象。出现异常时,MATLAB 创建 MException 对象,并在处理该错误的 catch 语句中返回该对象。
您不需要对 catch 语句指定任何参量。如果您不需要 MException 对象提供的任何信息或方法,仅需指定 catch 关键字。
MException 对象是由失败的程序中的内部代码构造的。该对象的属性中包含有关错误的信息,可用于确定发生了什么以及如何继续操作。MException 对象还提供多种方法的访问权限,从而使您能够对异常作出响应。
进入 catch 块之后,MATLAB 按顺序执行这些语句。这些语句可尝试
解决错误。
捕获有关错误的更多信息。
打开
MException对象中找到的信息并作出适当响应。清理受失败代码影响的环境。
catch 块通常以 rethrow 命令结尾。rethrow 使 MATLAB 退出当前函数,并使调用堆栈信息保持为首次抛出异常时的状态。如果此函数处于最高级别(即它不由另一个函数调用),则程序终止。如果失败的函数由另一个函数调用,则程序返回到该函数。程序执行过程会继续返回到较高级别的函数,除非其中任何调用是在较高级别的 try 块中进行的,在这种情况下程序会执行各自的 catch 块。
有关如何处理异常的建议
以下是读取图像文件内容的示例。它包括详细的错误处理,并演示一些针对错误可以采取的建议措施。
图像读取函数以几种方式抛出和捕获错误。
第一个
if语句检查函数调用时是否带输入参量。如果没有指定输入参量,程序会抛出错误,并建议提供输入参量来更正错误。try块尝试打开和读取文件。如果打开或读取操作失败,程序会捕获生成的异常并将MException对象保存在变量ME1中。catch块用于检查是否找不到指定的文件。如果是,则程序会提供以下可能性:通过使用修改后的扩展名重试操作,以使用常见的文件扩展名变化形式(例如jpeg而不是jpg)。这是通过嵌套在原始try/catch中的try/catch语句完成的。
function d_in = read_image(filename)
% Check the number of input arguments.
if nargin < 1
me = MException('MATLAB:notEnoughInputs','Not enough input arguments.');
aac = matlab.lang.correction.AppendArgumentsCorrection('"image.png"');
me = me.addCorrection(aac);
throw(me);
end
% Attempt to read file and catch an exception if it arises.
try
fid = fopen(filename,'r');
d_in = fread(fid);
catch ME1
% Get last segment of the error identifier.
idSegLast = regexp(ME1.identifier,'(?<=:)\w+$','match');
% Did the read fail because the file could not be found?
if strcmp(idSegLast,'InvalidFid') && ...
~exist(filename,'file')
% Yes. Try modifying the filename extension.
switch ext
case '.jpg' % Change jpg to jpeg
filename = strrep(filename,'.jpg','.jpeg');
case '.jpeg' % Change jpeg to jpg
filename = strrep(filename,'.jpeg','.jpg');
case '.tif' % Change tif to tiff
filename = strrep(filename,'.tif','.tiff');
case '.tiff' % Change tiff to tif
filename = strrep(filename,'.tiff','.tif');
otherwise
fprintf('File %s not found\n',filename);
rethrow(ME1);
end
% Try again, with modified filenames.
try
fid = fopen(filename,'r');
d_in = fread(fid);
catch ME2
fprintf('Unable to access file %s\n',filename);
ME2 = addCause(ME2,ME1);
rethrow(ME2)
end
end
end该示例展示了一些可用来对异常作出响应的操作。
将
MException对象的identifier字段与可能的错误原因进行对比。在本例中,函数检查标识符是否以'InvalidFid'结尾,以此结尾则表示找不到文件。使用嵌套的
try/catch语句,用改进的输入重试该操作。在本例中,函数使用文件扩展名的已知变体重新尝试打开和读取操作。显示适当的消息。
将第一个
MException对象添加到第二个对象的cause字段中。向
MException对象添加建议的更正。重新抛出异常。这会停止程序的执行并显示错误消息。
此外,建议清理掉任何不需要的错误结果。例如,关闭在错误发生后保持打开的图窗。