arrays - 如何识别 MATLAB 中数据存储在数组边界之外的位置?

标签 arrays matlab matlab-coder

我正在尝试使用 MATLAB Coder 将代码从 Matlab 转换为 MEX 文件。如果我有以下形式的代码片段:

x = zeros(a,1)
x(a+1) = 1

然后在 Matlab 中,这将调整数组的大小以容纳新元素,而在 MEX 文件中,这将给出“索引超出矩阵维度”错误。我希望代码中有很多地方会发生这种情况。

我想要做的是运行代码的 MATLAB 版本(不使用编码器),但让 MATLAB 在调整数组大小时生成错误或警告,因为我分配给了边界之外的东西。 (我可以只使用 MEX 文件并查看错误弹出的位置,但这需要在每次更改代码时使用 MATLAB Coder 重建整个 MEX 文件,这需要一段时间。)

有没有办法做到这一点? MATLAB 中是否有任何类型的设置可以关闭“如果您分配给越界索引,则自动调整大小”,或者在发生这种情况时发出警告?

最佳答案

编辑: As of Matlab 2015b , Coder 现在有运行时错误检查作为一个选项(来自 Matlab 发行说明):

In R2015b, generated standalone libraries and executables can detect and report run-time errors such as out-of-bounds array indexing. In previous releases, only generated MEX detected and reported run-time errors.

By default, run-time error detection is enabled for MEX. By default, run-time error detection is disabled for standalone libraries and executables.

To enable run-time error detection for standalone libraries and executables:

At the command line, use the code configuration property RuntimeChecks.

cfg = coder.config('lib'); % or 'dll' or 'exe'

cfg.RuntimeChecks = true;

codegen -config cfg myfunction

Using the MATLAB Coder app, in the project build settings, on the Debugging tab, select the Generate run-time error checks check box.

The generated libraries and executables use fprintf to write error messages to stderr and abort to terminate the application. If fprintf and abort are not available, you must provide them. Error messages are in English.

See Run-Time Error Detection and Reporting in Standalone C/C++ Code and Generate Standalone Code That Detects and Reports Run-Time Errors.



原答案:
关于声明一个从 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如果围绕它的声明。然后你可以在你的代码中使用它。

它不像重载 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 中创建的代码将导致段错误或 MEX 错误。另一种方法是使用 end 的强大功能。函数保持分配整洁(但被截断。)如果我们将分配更改为:
t(1,1:min(end,numel(tempstring))) = tempstring(1:size(t, 2));
t尺寸将保持不变,但分配将被截断。 end的使用允许在分配期间进行边界检查。在某些情况下,这可能是处理问题的好方法,并且可以让您确信永远不会超出界限,但显然在某些情况下这是非常不可取的(并且不会在 MATLAB 中给您错误消息。)

MATLAB 提供的另一个有用的工具是编辑器本身。如果您使用 %#codegen在您的代码中添加标记,它将向编辑器的语法检查器发出信号以突出显示各种代码生成问题,包括您通过索引明显增加数组大小的地方。这不能捕捉所有情况,但它是一个很好的帮助。

Editor example with codegen

最后一点。正如问题中提到的,Coder 生成的 MEX 文件会在分配时给您一个“索引超出矩阵维度”错误,并且会优雅地退出,甚至会告诉您发生错误的原始代码行。由 Coder 生成的 C 库没有这样好的行为或边界检查,并且会在没有诊断的情况下完全出现段错误。中间答案是完全按照您正在做的事情做,即将代码作为 MEX 运行。这对你的问题不是很有帮助(如你所说,重建 MEX 可能需要时间),但对于我们这些为外部 C 代码的冷酷世界编码的人来说,能够运行 MEX 的中间测试找到这些错误是救命稻草。

归根结底,这是 MATLAB 和 Coder 生成的 C 代码之间的行为差​​异,它可能是重大问题的根源。在我自己的代码中,正是出于这个原因,我对数组访问和增长非常小心。这是我希望在 Coder 工具本身中看到改进的一个领域,但是在编写针对 Coder 的 MATLAB 代码时,有一些方法需要非常小心。

关于arrays - 如何识别 MATLAB 中数据存储在数组边界之外的位置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29151666/

相关文章:

javascript - 在 Javascript 中用 null 填充缺失索引的值的最佳方法

python - 将行添加到 numpy 数组而不丢失以前存储的数据

matlab - 如何在Matlab的Classification Learner App中传递数据集

c++ - 使用 Matlab Coder 将 Matlab m 文件转换为 C/C++ 代码,包括 mex 文件 (mxArray)

java - 如何从方法返回数组?

javascript - 输出javascript数组的内容

matlab - MATLAB:从先前版本运行功能

matlab - Matlab 中基于 Excel 输入的动态列大小调整

c - MATLAB 嵌入式 C 函数问题

无法使用 Matlab Coder 将 Matlab 代码转换为 C 代码