对异常作出响应
概述
默认情况下,当引发异常时,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
对象添加建议的更正。重新引发异常。这会停止程序的执行并显示错误消息。
此外,建议清理掉任何不需要的错误结果。例如,关闭在错误发生后保持打开的图窗。