Main Content

Handle Object Limitations for Code Generation

The code generator statically determines the lifetime of a handle object. When you use handle objects, this static analysis has certain restrictions.

With static analysis the generated code can reuse memory rather than rely on a dynamic memory management scheme, such as reference counting or garbage collection. The code generator can avoid dynamic memory allocation and run-time automatic memory management. These generated code characteristics are important for some safety-critical and real-time applications.

For limitations, see:

The code generator analyzes whether all variables are defined prior to use. Undefined variables or data types cause an error during code generation. In certain circumstances, the code generator cannot determine if references to handle objects are defined. See References to Handle Objects Can Appear Undefined.

A Variable Outside a Loop Cannot Refer to a Handle Object Allocated Inside a Loop

Consider the handle class mycls and the function 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

If you try to generate code for the usehandle1 function, the code generator produces an error. The error occurs because:

  • Handle objects are allocated inside the for-loop

  • One of these handle objects is used outside of the for-loop

A Handle Object That a Persistent Variable Refers To Must Be a Singleton Object

If a persistent variable refers to a handle object, the code generator allows only one instance of the object during the program’s lifetime. The object must be a singleton object. To create a singleton handle object, enclose statements that create the object in the if isempty() guard for the persistent variable.

For example, consider the class mycls and the function usehandle2. The code generator reports an error for usehandle2 because p.prop refers to the mycls object that the statement inner = mycls creates. This statement creates a mycls object for each invocation of usehandle2.

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

If you move the statements inner = mycls and inner.prop = x inside the if isempty() guard, code generation succeeds. The statement inner = mycls executes only once during the program’s lifetime.

function usehandle2(x)
assert(isa(x, 'double'));
persistent p;
if isempty(p)
    inner = mycls;
    inner.prop = x;
    p = mycls;
    p.prop = inner;
end

Consider the function usehandle3. The code generator reports an error for usehandle3 because the persistent variable p refers to the mycls object that the statement myobj = mycls creates. This statement creates a mycls object for each invocation of usehandle3.

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

If you make myobj persistent and enclose the statement myobj = mycls inside an if isempty() guard, code generation succeeds. The statement myobj = mycls executes only once during the program’s lifetime.

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

References to Handle Objects Can Appear Undefined

Consider the function refHandle that copies a handle object property to another object. The function uses a simple handle class and value class. In MATLAB®, the function runs without error.

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

During code generation, an error occurs:

Property 'v.prop.prop' is undefined on some execution paths.

Three variables reference the same memory location: x, y, and v.prop. The code generator determines that x.prop and y.prop share the same value. The code generator cannot determine that the handle object property v.prop.prop shares its definition with x.prop and y.prop. To avoid the error, define v.prop.prop directly.