概述
当 MATLAB 抛出异常时,它会捕获产生错误的信息,并将之保存在类 MException 对象的数据结构中。可以在程序中止之前捕获异常并通过 catch 命令访问为此异常构造的对象获得 MException 对象的访问权限。当抛出异常以响应用户代码中的错误时,将不得不创建一个新的 MException 对象并在该对象中存储有关错误的信息。本节主要说明 MException 类和该类构造的对象。
MException 类
下图显示了 MException 类对象的一种可能配置。该对象有四个属性:标识符(identifier),消息(message),堆栈(stack)和原因(cause)。每一属性都表示 MException 对象结构的一部分。堆栈字段是 N×1 的附加结构数组,每个结构标识一个函数,和来自调用堆栈的行号。 cause 字段是 MException 对象的 M×1 胞元数组,每个数组表示与当前对象相关的异常。

对象构造函数
任何检测到错误并抛出异常的代码必须构造一个 MException 对象,在该对象中记录和传输有关错误的信息。 MException 构造函数的语法是
ME = MException(identifier, message)其中 identifier 是一种 MATLAB 消息标识符,形式为
component:mnemonic用单引号括起来。消息是用单引号括起来的文本,用于描述错误。 输出 ME 是生成的 MException 对象。
如果你要响应异常而不是抛出异常,则不必构造 MException 对象。 该对象已由最初检测到错误的代码构造和填充。
MException 类的属性
MException 类有四个属性(identifier,message,stack,cause,)。 每一属性都表示 MException 对象结构的一部分,并且是只读的。
如果你忘了输入参数,直接调用 surf 函数,MATLAB 会抛出一个异常。如果你捕获这个异常,就能够看到 MException 对象结构的四个属性。
try surf catch ME ME end结果:
ME = MException with properties: identifier: 'MATLAB:narginchk:notEnoughInputs' message: 'Not enough input arguments.' cause: {} stack: [1×1 struct]stack 字段显示抛出异常的文件名,函数和行号:
ans = struct with fields: file: 'D:\Matlab 2017b\toolbox\matlab\graph3d\surf.m' name: 'surf' line: 49在这种情况下,cause 字段为空。
消息标识符
消息标识符是附加到错误或警告语句的标记,该错误或警告语句使得在 MATLAB 可以被唯一识别。你可以使用带有错误报告的消息标识符来更好地识别错误的来源,或者使用警告来控制程序中任何选定的警告子集。
消息标识符是只读字符向量,用于指定错误或警告的 component 和 mnemonic 标签。简单标识符的格式是
component:mnemonic
component 和 mnemonic之间用冒号分隔。如果标识符使用多个 component ,则需要多个冒号来分隔。消息标识符包含至少一个冒号。
消息标识符示例:
MATLAB:rmpath:DirNotFound
MATLAB:odearguments:InconsistentDataType
Simulink:actionNotTaken
TechCorp:OpenFile:notFoundInPath
component 和 mnemonic 字段都必须遵循以下语法规则:
标识符中的任何位置都不允许使用空格(空格或制表符)。
第一个字符必须是字母,不论大写或小写。
其余字符可以是字母数字或下划线。
component 和 mnemonic 没有长度限制。标识符也可以是空字符向量。
component 字段
component 字段指定了一个广泛的类别,在该类别下可以生成各种错误和警告。常用组件是特定产品或工具箱名称,例如MATLAB 或 Control,或者公司的名称,例如前面示例中的TechCorp。
还可以使用此字段指定多级组件。以下语句包含一个三级组件,后跟一个助记符标签:
TechCorp:TestEquipDiv:Waveform:obsoleteSyntax组件字段可以保证每个标识符的唯一性。因此,虽然内部 MATLAB 代码可能使用某个警告标识符,如 MATLAB:InconsistentDataType,但这并不妨碍相同的助记符的使用,只要在其前面加上唯一的组件即可。例如,
warning('TechCorp:InconsistentDataType', ... 'Value %s is inconsistent with existing properties.' ... sprocketDiam)
Mnemonic 字段mnemonic 字段通常用作与特定消息相关的标签。例如,在报告由于使用模糊语法而导致的错误时,可能需要使用以下简单组件和助记符:
MATLAB:ambiguousSyntaxMException 对象中的消息标识符
抛出异常时,创建一个适当的标识符,并在使用以下语法构造对象时将其保存到 MException 对象
ME = MException(identifier, text)示例:
ME = MException('AcctError:NoClient', ... 'Client name not recognized.'); ME.identifier ans = AcctError:NoClient响应异常时,可以从 MException 对象中提取消息标识符,如下所示。
try surf catch ME id = ME.identifier end id = MATLAB:narginchk:notEnoughInputs
错误消息的文本
MATLAB 中的错误消息是由程序代码发出并在 MException 对象中返回的只读字符向量。 该消息可以帮助用户确定故障的原因以及可能的补救措施。
抛出异常时,添加相应的错误消息并在使用语法构造对象时将其保存到MException对象。
ME = MException(identifier, text)
如果消息需要格式化规范(如 sprintf 函数),可以将此语法用于 MException 构造函数:
ME = MException(identifier,formatstring,arg1,arg2,...)
示例
S = 'Accounts'; f1 = 'ClientName'; ME = MException('AcctError:Incomplete', ... 'Field ''%s.%s'' is not defined.', S, f1); ME.message结果
ans = Field 'Accounts.ClientName' is not defined.
响应异常时,可以从 MException 对象中提取错误消息,如下所示:
示例
try surf catch ME msg = ME.message end结果
msg = Not enough input arguments.
调用堆栈
MException 对象的堆栈字段标识检测到错误的行号,函数和文件名。 如果在被调用函数中发生错误,如下例所示,堆栈字段不仅包含当前错误的行号,函数名和文件名,还包含每个调用函数的行号,函数名和文件名。 在这种情况下,堆栈是 Nx1 数组,其中 N 表示调用堆栈的深度。 也就是说,堆栈字段显示发生异常的函数名称和行号,调用者的名称和行号,调用者的调用者等,直到达到最顶层的函数。
抛出异常时,MATLAB 将堆栈信息存储在堆栈字段中。 不过该字段是只读的。
例如,假设您有三个函数驻留在两个单独的文件中:
mfileA.m ========================= . . 42 function A1(x, y) 43 B1(x, y); mfileB.m ========================= . . 8 function B1(x, y) 9 B2(x, y) . . 26 function B2(x, y) 27 . 28 . 29 . 30 . 31 % Throw exception here在变量 ME 中捕获异常,然后检查堆栈字段:
for k=1:length(ME.stack) ME.stack(k) end结果
ans = file: 'C:\matlab\test\mfileB.m' name: 'B2' line: 31 ans = file: 'C:\matlab\test\mfileB.m' name: 'B1' line: 9 ans = file: 'C:\matlab\test\mfileA.m' name: 'A1' line: 43
cause 数组
在某些情况下,不仅要记录有关导致程序停止的命令,还要记录代码捕获的其它异常信息。 你可以将这些额外的 MException 对象保存在主要异常的 cause 字段中。
MException 的 cause 字段是相关 MException 对象的可选胞元数组。 将对象添加到原因单元数组时,必须使用以下语法:
primaryException = addCause(primaryException, secondaryException)
此示例尝试将数组 D 分配给变量 X。如果 D 数组不存在,则代码尝试从 MAT 文件加载它,然后重试将其分配给 X。如果加载失败,则新的 MException 对象(ME3) 构造用于存储前两个错误(ME1 和 ME2)的原因:
try X = D(1:25) catch ME1 try filename = 'test200'; load(filename); X = D(1:25) catch ME2 ME3 = MException('MATLAB:LoadErr', ... 'Unable to load from file %s', filename); ME3 = addCause(ME3, ME1); ME3 = addCause(ME3, ME2); end end此时,在 ME3 的 cause 字段中就有了两个异常:
ME3.cause ans = [1x1 MException] [1x1 MException]检查 ME3 的 cause 字段:
ME3.cause{:} ans = MException object with properties: identifier: 'MATLAB:UndefinedFunction' message: 'Undefined function or method 'D' for input arguments of type 'double'.' stack: [0x1 struct] cause: {} ans = MException object with properties: identifier: 'MATLAB:load:couldNotReadFile' message: 'Unable to read file test204: No such file or directory.' stack: [0x1 struct] cause: {}
MException 类的方法
有十种方法可以与 MException 类一起使用。 这些方法的名称区分大小写。
| MException.addCause | 将 MException 附加到另一个 MException 的 cause 字段 |
| MException.getReport | 根据当前异常返回格式化消息 |
| MException.last | 返回最后一次未捕获的异常(静态方法) |
| MException.rethrow | 重新发出先前捕获的异常 |
| MException.throw | 发出异常 |
| MException.throwAsCaller | 发出异常,但忽略堆栈字段中的当前堆栈帧 |
参考资料:
1.MATLAB 官方文档:https://ww2.mathworks.cn/help/
本文详细介绍了MATLAB中的异常处理机制,重点讲解了MException类及其对象的使用。MException对象在MATLAB抛出异常时存储错误信息,包括标识符、消息、堆栈和原因,帮助开发者定位和理解错误。文章还展示了如何通过构造函数创建和操作MException对象,以及如何使用其方法进行异常管理。
425

被折叠的 条评论
为什么被折叠?



