【Matlab】异常处理:MException
文章目录
- 一、为什么需要异常处理
- 二、matlab 异常处理
- 2.1 预定义异常与自定义异常
- 2.2 MException 对象
- 2.21 捕获预定义异常
- 2.22 MException 对象的属性
- 2.23 自定义异常:MException
- 2.24 MException 对象函数
一、为什么需要异常处理
🪄 程序总会出错。语法错误是最容易发现和修正的类型,因为编辑器通常会直接提示这些问题。然而,还有一些错误不会在编写阶段暴露出来,它们只会在特定的运行条件下才显现出来。
在编程中,可以尝试让程序对各种可能的情况都作出合理处理,但这几乎是不可能完全做到的。一个更实用的角度是:让程序专注于处理正常的、预期内的情景,而将其它所有情况都统一归为异常。这些异常可能代表真正的错误,也可能只是“不符合预期的状态”。 (比如除以0是错误,也可以说是异常,而文件没找到则称为异常更合适。)
对这类异常,程序不应盲目崩溃,而应通过异常处理机制来捕获它们,并采取恰当的应对措施。例如:
- 记录日志以便后续分析;
- 输出有意义的提示信息;
- 尝试恢复运行或采用默认值继续执行;
- 在必要时安全退出程序。
这种思路的核心,不是让程序永远不出错,而是让它在出错时也能有序、可控地应对。
举个例子:
- 你的程序是一个网页,不能因为网页上一个图片没加载出来,程序就直接崩溃。
- 你要读取一个目录下很多excel,并画图,其中有个excel格式不对,程序就停止运行吗?
🟠异常处理也不是万能的,如对逻辑错误就没有效果。即语法正确、能运行,但结果不是预期的。这种错误就只能检查代码、添加断言或者debug了。
二、matlab 异常处理
2.1 预定义异常与自定义异常
检测到错误并抛出异常的任何 MATLAB 代码都构造一个 MException 对象。
该 MException 对象包含有关错误的可检索信息包括标识符、消息、堆栈等)。MATLAB 可以抛出预定义异常或你构造的异常。
MATLAB 并没有一个固定的、可枚举的预定义异常“清单”。
简单来说,如果是matlab自己抛出一个错误(异常),就是预定义的;而用户使用throw等函数主动创建并抛出一个 MException 对象,则属于“你构造的异常”。
🧩🧩快速区分:
| 特性 | MATLAB预定义异常 | 用户构造的异常 |
|---|---|---|
| 谁抛出? | MATLAB执行引擎 | 开发者(通过 throw 或 error 函数) |
| 为什么抛出? | 违反了 MATLAB 的底层语法或操作规则 | 违反了开发者自己定义的程序逻辑或条件 |
| 错误标识符 | 由 MATLAB 预先定义和分配 | 由开发者自行设计和命名 |
| 示例 | 索引超出数组边界 (MATLAB:badsubscript) | 函数输入必须为正数,但收到了负数 (myApp:InvalidInput) |
详细说明:
-
(1)MATLAB的预定义异常
- 抛出者: MATLAB执行引擎。当代码违反了语言的内在规则时,MATLAB会自动侦测到这些“不合法”的操作,并主动创建并抛出一个
MException对象来中断程序流程。 - 触发时机: 在执行内置函数或基本操作时发生错误。例如:
- 语法错误: 代码不符合MATLAB的语法规则。
- 运行时错误: 试图对一个3x3矩阵的第10个元素进行索引 (索引越界)。
- 逻辑错误: 调用函数时,提供的参数数量不正确。
- 环境错误: 试图读取一个不存在的文件。
- 目的: 通知开发者,代码触发了一个MATLAB内部无法正常处理的状况。标识符 (
identifier): 通常是格式化的、由MATLAB预先定义好的字符串,如MATLAB:badsubscript或MATLAB:UndefinedFunction。这些标识符是固定的,并且有据可查。
- 抛出者: MATLAB执行引擎。当代码违反了语言的内在规则时,MATLAB会自动侦测到这些“不合法”的操作,并主动创建并抛出一个
-
(2)用户构造的异常
- 抛出者: 开发者/程序员自己。开发者在自己的代码中,通过明确调用
throw或error函数来主动创建并抛出一个MException对象。 - 触发时机: 当代码的执行虽然没有违反MATLAB的底层规则,但却不符合我们自己程序设计的业务逻辑或预期条件时。例如:
- 参数验证: 一个函数要求输入值必须是正数,但用户传入了一个负数。这对于MATLAB本身来说是合法的(负数也是一个有效的数值),但对于这个特定函数的功能来说是不合法的。
- 状态检查: 程序要求在执行某个操作前必须先完成初始化,但检测到初始化未完成。
- 业务规则: 在一个银行系统中,取款金额大于账户余额。
- 目的: 主动地、可控地中断程序,并告知调用者(或其他开发者)一个不符合预期的、特定于当前应用逻辑的错误已经发生。
标识符 (identifier): 由开发者自己定义。为了保持良好风格,通常会遵循component:mnemonic的格式,例如myApp:InvalidInput:NegativeValue。这使得错误处理代码可以精确地捕获并识别出我们自己定义的特定错误。
- 抛出者: 开发者/程序员自己。开发者在自己的代码中,通过明确调用
2.2 MException 对象
2.21 捕获预定义异常
前面说了:检测到错误并抛出异常的任何 MATLAB 代码都构造一个 MException 对象。
如果是预定义的异常,我们如何捕获这个异常呢?
🟢 使用try...catch语句:这是唯一推荐使用的异常捕获与处理语句。
如:使用surf函数画一个三维图,却没有给他任何参数
trysurf
catch MExceptionMException.message
end
输出:

🟢详解: try关键字 后面放你想要执行的语句,如果语句有错误,matlab会自动创建一个MException对象,使用catch 关键字来捕捉这个异常,并在后面放你的异常处理代码。
MException可以缩写为ME,通常使用缩写,且只能是这2个。
2.22 MException 对象的属性
🔎前面我们已经成功捕获了一个预定义的MException 对象,现在看看这个对象有哪些属性。
直接命令行打印就看到了:
>> MEME = MException - 属性:identifier: 'MATLAB:narginchk:notEnoughInputs'message: '输入参数的数目不足。'cause: {}stack: [2×1 struct]Correction: []
有5个属性,它们都是只读的,解释如下:
| 属性 | 类型 | 说明 |
|---|---|---|
| identifier | char | 错误的唯一标识符,用于标识异常类型,例如 'MATLAB:badsubscript' |
| message | char | 异常的详细描述信息 (错误消息) |
| cause | cell array of MException | 引发当前异常的其他异常对象(可以为空),用于嵌套异常追踪 |
| stack | struct array | 异常发生时的调用堆栈信息,每个元素包含 file(文件名)、name(函数名)、line(行号) |
| Correction | 是一个对象 | 对异常的建议修复。这个不常用 |
异常发生时的调用堆栈信息:

🟢如果你不做异常处理,那么程序的错误显示的就是错误消息和调用堆栈信息:即我们常见的报错

2.23 自定义异常:MException
即自己定义一个MException对象。
语法:
ME = MException(errID,msg)
ME = MException(errID,msg,A1,...,An)
MException是类,这里是使用类的构造函数来构建一个MException对象。不是函数哈。
参数:
🧩(1) errID:(字符向量、字符串标量)错误标识符,即MException对象的identifier属性值
错误标识符包括一个或多个组件字段和一个助记键字段。各字段必须用冒号分隔。例如,具有组件字段 component 和助记键字段 mnemonic 的错误标识符指定为 ‘component:mnemonic’。
-
组件字段通常指定可能出现各种错误的产品或功能。例如,错误标识符
MATLAB:TooManyInputs有组件字段 MATLAB,这意味着在 MATLAB 中抛出异常。可以重用同一个助记键TooManyInputs,但要在它前面加上不同组件。 -
错误标识符的助记键字段通常是特定于错误问题的标记。例如,当报告由于在 MATLAB 中使用模糊语法而导致的错误时,可以将错误标识符指定为 ‘MATLAB:ambiguousSyntax’。
组件字段和助记键字段都必须以字母开头。其余字符可以是字母数字字符(A–Z、a–z、0–9)和下划线。errID 中不能出现空白字符。
简单来说就是,错误来自哪里,是什么错误。
🧩(2)msg:(字符向量、字符串标量)错误消息,即MException对象的message属性值。
有关错误原因以及如何进行更正的信息,指定为字符向量或字符串标量。要设置文本格式,请使用转义序列,例如 \t 或 \n。还可以使用 sprintf 函数支持的任何格式设定符,例如 %s 或 %d。使用 A 输入参量指定转换设定符的值。
🧩(3)A1,…,An:(字符向量、字符串标量、数值标量)替换值
用来替换 msg 中的转换设定符的一个或多个值,每个值指定为字符向量、字符串标量或数值标量。。
就类似于sprintf 函数。
下面的结果是完全一样的:
clear
clc% 提前写好字符串
x = 9;
str = sprintf('错误的值:%d',x);
ME = MException('TEST:wrongValue',str); % 直接把str换成:sprintf('错误的值:%d',x)也是一样的ME% 使用替换值
ME = MException('TEST:wrongValue','错误的值:%d',x);ME
2.24 MException 对象函数
| 方法 | 说明 |
|---|---|
| throw | 引发异常,将当前 MException 对象抛出 |
| MException.last | 返回最后一次未被捕获的异常对象 |
| rethrow | 重新引发以前捕获的异常 |
| throwAsCaller | 抛出异常,但显示为在调用该函数的位置发生 |
| addCause | 为当前异常记录其他引发它的异常(嵌套异常) |
| addCorrection | 为异常提供建议的修复措施 |
| getReport | 获取异常的完整错误报告,包括消息和堆栈信息 |
📗 (1)throw:引发异常
语法:
throw(exception)
根据 MException 对象 exception 中包含的信息引发异常。该异常终止当前正在运行的函数,并将控制权返回到键盘或封闭的 catch 块。从 try/catch 语句外部引发异常时,MATLAB® 将错误消息显示在命令行窗口中。
throw 函数不同于 throwAsCaller 和 rethrow 函数,它从 MATLAB 调用函数的位置创建堆栈跟踪。
可以通过 try/catch 语句或 MException.last 函数访问 MException 对象。
例:如果输入的不是:var,就会在命令行显示异常
clear
clc
str = input('Type a variable name: ','s');
if ~exist(str,'var')ME = MException('MyComponent:noSuchVariable', ...'Variable %s not found',str);throw(ME)
end

📗 (2)MException.last:返回最后未捕获的异常
语法:
exception = MException.last
MException.last('reset')
- exception = MException.last 返回最近引发的、未捕获的 MException 对象的内容。如果 try/catch 语句捕获到了最后一个异常,则不设置 MException.last。MException.last 是静态函数。
- MException.last(‘reset’) 清除从 MException.last 返回的异常的属性。它将 MException identifier 和 message 属性设置为空字符向量,将 stack 属性设置为 0×1 结构体,将 cause 属性设置为一个空的元胞数组。
