主要内容

代码生成的句柄对象限制

代码生成器静态确定句柄对象的生存时间。当您使用句柄对象时,这种静态分析有一定的限制。

通过静态分析,生成的代码可以重用内存,而不是依赖动态内存管理方案,如引用计数或垃圾回收。代码生成器可以避免动态内存分配和运行时自动内存管理。这些生成的代码特性对于一些安全关键型和实时应用至关重要。

有关限制,请参阅:

代码生成器分析是否所有变量在使用前都已定义。未定义的变量或数据类型会在代码生成过程中导致错误。在某些情况下,代码生成器无法确定是否定义了对句柄对象的引用。请参阅对句柄对象的引用可能看起来未定义

循环外的变量无法引用在循环内分配的句柄对象

以句柄类 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 = myclsinner.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' 在某些执行路径中未定义。要进行代码生成,所有变量在使用前都必须完全定义。)

以下三个变量引用同一内存位置:xyv.prop。代码生成器确定 x.propy.prop 共享相同的值。代码生成器无法确定句柄对象属性 v.prop.propx.propy.prop 共享其定义。为了避免错误,请直接定义 v.prop.prop

另请参阅

| (MATLAB Coder) |

主题