代码生成的句柄对象限制
代码生成器静态确定句柄对象的生存时间。当您使用句柄对象时,这种静态分析有一定的限制。
通过静态分析,生成的代码可以重用内存,而不是依赖动态内存管理方案,如引用计数或垃圾回收。代码生成器可以避免动态内存分配和运行时自动内存管理。这些生成的代码特性对于一些安全关键型和实时应用至关重要。
有关限制,请参阅:
代码生成器分析是否所有变量在使用前都已定义。未定义的变量或数据类型会在代码生成过程中导致错误。在某些情况下,代码生成器无法确定是否定义了对句柄对象的引用。请参阅对句柄对象的引用可能看起来未定义。
循环外的变量无法引用在循环内分配的句柄对象
以句柄类 mycls 和函数 usehandle1 为例。
classdef mycls < handle properties prop end methods function obj = mycls(x) obj.prop = x; end end end
function y = usehandle1(n) c = cell(1,n); for i = 1:n c{i} = mycls(i); % Handle object allocated inside loop end y = c{n}.prop; % Handle object referenced outside loop end
如果您尝试为 usehandle1 函数生成代码,代码生成器会产生错误。出现该错误的原因是:
句柄对象是在
for循环内分配的这些句柄对象之一在
for循环外使用
持久变量引用的句柄对象必须为单例对象
如果持久变量引用句柄对象,代码生成器在程序的生存时间内只允许使用该对象的一个实例。该对象必须为单例对象。要创建单例句柄对象,请在持久变量的 if isempty() 保护中包含创建该对象的语句。
以类 mycls 和函数 usehandle2 为例。代码生成器对 usehandle2 报告错误,因为 p.prop 引用语句 inner = mycls 创建的 mycls 对象。此语句为 usehandle2 的每次调用创建一个 mycls 对象。
classdef mycls < handle properties prop end end
function usehandle2(x) assert(isa(x, 'double')); persistent p; inner = mycls; inner.prop = x; if isempty(p) p = mycls; p.prop = inner; end
如果将语句 inner = mycls 和 inner.prop = x 移至 if isempty() 保护内,代码生成将会成功。语句 inner = mycls 在程序的生存时间内只执行一次。
function usehandle2(x) assert(isa(x, 'double')); persistent p; if isempty(p) inner = mycls; inner.prop = x; p = mycls; p.prop = inner; end
以 usehandle3 函数为例。代码生成器对 usehandle3 报告错误,因为持久变量 p 引用语句 myobj = mycls 创建的 mycls 对象。此语句为 usehandle3 的每次调用创建一个 mycls 对象。
function usehandle3(x) assert(isa(x, 'double')); myobj = mycls; myobj.prop = x; doinit(myobj); disp(myobj.prop); function doinit(obj) persistent p; if isempty(p) p = obj; end
如果使 myobj 持久化并将语句 myobj = mycls 包含在 if isempty() 保护中,代码生成将会成功。语句 myobj = mycls 在程序的生存时间内只执行一次。
function usehandle3(x) assert(isa(x, 'double')); persistent myobj; if isempty(myobj) myobj = mycls; end doinit(myobj); function doinit(obj) persistent p; if isempty(p) p = obj; end
对句柄对象的引用可能看起来未定义
以函数 refHandle 为例,该函数将句柄对象属性复制到另一个对象。该函数使用简单的句柄类和值类。在 MATLAB® 中,函数会正常运行而没有报错。
function [out1, out2, out3] = refHandle() x = myHandleClass; y = x; v = myValueClass(); v.prop = x; x.prop = 42; out1 = x.prop; out2 = y.prop; out3 = v.prop.prop; end
classdef myHandleClass < handle properties prop end end
classdef myValueClass properties prop end end
在代码生成过程中,会出现错误:
Property 'v.prop.prop' is undefined on some execution paths.For code generation, all variables must be fully defined before use.(属性 'v.prop.prop' 在某些执行路径中未定义。要进行代码生成,所有变量在使用前都必须完全定义。)
以下三个变量引用同一内存位置:x、y 和 v.prop。代码生成器确定 x.prop 和 y.prop 共享相同的值。代码生成器无法确定句柄对象属性 v.prop.prop 与 x.prop 和 y.prop 共享其定义。为了避免错误,请直接定义 v.prop.prop。
另请参阅
assert | codegen (MATLAB Coder) | properties
主题
- 解决问题:变量在使用前必须完全定义 (MATLAB Coder)