代码生成的句柄对象限制
代码生成器静态确定句柄对象的生存时间。当您使用句柄对象时,这种静态分析有一定的限制。
通过静态分析,生成的代码可以重用内存,而不是依赖动态内存管理方案,如引用计数或垃圾回收。代码生成器可以避免动态内存分配和运行时自动内存管理。这些生成的代码特性对于一些安全关键型和实时应用至关重要。
有关限制,请参阅:
代码生成器分析是否所有变量在使用前都已定义。未定义的变量或数据类型会在代码生成过程中导致错误。在某些情况下,代码生成器无法确定是否定义了对句柄对象的引用。请参阅对句柄对象的引用可能看起来未定义。
循环外的变量无法引用在循环内分配的句柄对象
以句柄类 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)