编辑:As of Matlab 2015b,Coder 现在可以选择运行时错误检查(来自 Matlab 发行说明):
在 R2015b 中,生成的独立库和可执行文件可以检测和报告运行时错误,例如越界数组索引。在
以前的版本,仅生成 MEX 检测并报告运行时
错误。
默认情况下,为 MEX 启用运行时错误检测。经过
默认情况下,独立库禁用运行时错误检测
和可执行文件。
启用独立的运行时错误检测
库和可执行文件:
在命令行,使用代码
配置属性RuntimeChecks。
cfg = coder.config('lib'); % 要么
'dll' 或 'exe'
cfg.RuntimeChecks = true;
codegen -config cfg myfunction
使用 MATLAB Coder 应用程序,在项目构建设置中,
在调试选项卡上,选择生成运行时错误检查检查
盒子。
生成的库和可执行文件使用fprintf编写
错误消息到 stderr 并中止以终止应用程序。如果
fprintf 和 abort 不可用,您必须提供它们。错误
消息是英文的。
请参阅 Run-Time Error Detection and Reporting in Standalone C/C++ Code 和 Generate Standalone Code That Detects and Reports Run-Time Errors。
原答案:
cmets 中关于声明从 double 子类化的类的答案,其中 subsref 方法被重载以禁止增长,这将是一种好方法。
另一种简单的方法是在整个代码中(在每个循环迭代中或在函数的底部)散布assert 命令,以断言大小没有增加超过分配的大小。
例如,如果您的代码格式为:
x = zeros(a,1)
x(a+1) = 1
... lots of other operations
if coder.target('MATLAB')
assert(isequal(size(x), [a,1]), 'x has been indexed out of bounds')
end
如果分配了任何扩展数组的值,这将使断言失败。
为了使这更整洁,您甚至可以创建一个函数来检查您关心的所有变量,再次将coder.target if 语句包裹在它周围。然后你可以把它洒在你的代码中。
它不像重载 double 类那样优雅,但另一方面它根本不会给编译的代码增加任何开销。它也不会在溢出发生时准确地给你错误,但它会让你相信代码在各种情况下都能正常工作。
另一种让您对分配更有信心的方法是在可能合适的情况下对分配进行自己的边界检查。我在作业中看到的一个常见问题是这样的。我们有一个分配的数组,并且正在从另一个数组中复制数据并分配向量。例如,考虑以下情况:
t = char(zeros(5,7)); % Allocate a 5 by 7 char array
tempstring = 'hello to anyone'; % Here's a string we want to put into it.
t(1, 1:numel(tempstring)) = tempstring; % A valid assignment in MATLAB
>> size(t)
ans =
5 15
哦,哦,你关心的问题已经发生了:t 数组在赋值过程中自动调整大小,这在 MATLAB 中有效,但在 Coder 中创建的代码会导致 segfault 或 MEX 错误。另一种方法是使用end 函数的强大功能来保持赋值整洁(但被截断)。如果我们将赋值更改为:
t(1,1:min(end,numel(tempstring))) = tempstring(1:size(t, 2));
t 的大小将保持不变,但分配将被截断。使用end 允许在分配期间进行边界检查。在某些情况下,这可能是处理问题的好方法,并且会让您确信永远不会超出界限,但显然在某些情况下这是非常不可取的(并且不会在 MATLAB 中给您错误消息。) /p>
MATLAB 提供的另一个有用工具是编辑器本身。如果您在代码中使用%#codegen 标记,它将向编辑器的语法检查器发出信号以突出显示各种代码生成问题,包括您明显通过索引增加数组大小的地方。这不能捕捉所有情况,但它是一个很好的帮助。
最后一点。如问题中所述,Coder 生成的 MEX 文件会在分配时给您“索引超出矩阵维度”错误,并且会优雅地退出,甚至会告诉您发生错误的原始代码行。从 Coder 生成的 C 库没有这样好的行为或边界检查,并且会在没有诊断的情况下完全出现段错误。中间的答案是完全按照您正在做的事情,即将代码作为 MEX 运行。这对您的问题没有多大帮助(正如您所说,重建 MEX 可能需要时间),但对于我们这些为外部 C 代码的冷酷世界编写代码的人来说,能够运行 MEX 的中间测试以找到这些错误是救命稻草。
归根结底,这是 MATLAB 和 Coder 生成的 C 代码之间的行为差异,它可能是重大问题的根源。在我自己的代码中,正是出于这个原因,我对数组访问和增长非常小心。这是我希望看到 Coder 工具本身改进的一个领域,但是在编写针对 Coder 的 MATLAB 代码时,有一些方法需要非常小心。