Обработайте объектные ограничения для генерации кода

Генератор кода статически определяет время жизни объекта указателя. Когда вы используете объекты указателя, этот статический анализ имеет определенные ограничения.

Со статическим анализом сгенерированный код может снова использовать память, а не использовать схему управления динамической памятью, такую как подсчет ссылок или сборка мусора. Генератор кода может избежать динамического выделения памяти и автоматического управления памятью во время выполнения. Эти характеристики сгенерированного кода важны для некоторых критических по отношению к безопасности и приложений реального времени.

Для ограничений см.:

Генератор кода анализирует, заданы ли все переменные до использования. Неопределенные переменные или типы данных вызывают ошибку во время генерации кода. При определенных обстоятельствах генератор кода не может определить, заданы ли ссылки, чтобы обработать объекты. Смотрите, что Ссылки, чтобы Обработать Объекты Могут Казаться Неопределенными.

Переменная вне цикла не может относиться к объекту указателя, выделенному в цикле

Считайте класс Handle mycls и функция usehandle1.

classdef mycls < handle
   properties
       prop
   end
   
   methods
       function obj = mycls(x)
       obj.prop = x;
       end
   end
end
function y = usehandle1
p = mycls(0); % Instance of mycls with prop value 10 created

for i = 1:10
    p = mycls(i); % Handle object allocated inside loop
end

y = p.prop; % Handle object referenced outside loop
end

При попытке сгенерировать код для usehandle1 функция, генератор кода производит ошибку. Ошибка происходит потому что:

  • Объект указателя выделяется в for цикл. Переменная p.prop относится к этому объекту указателя.

  • Вне цикла, переменной x относится к свойству prop объект указателя.

Объектом указателя, к которому относится персистентная переменная, должен быть объект Singleton

Если персистентная переменная относится к объекту указателя, генератор кода позволяет только один экземпляр объекта в течение времени жизни программы. Объект должен быть объектом singleton. Чтобы создать одноэлементный объект указателя, заключите операторы, которые создают объект в if isempty() охраняйте для персистентной переменной.

Например, считайте класс mycls и функция usehandle2. Генератор кода сообщает об ошибке для usehandle2 потому что p.prop относится к mycls возразите что оператор inner = mycls создает. Этот оператор создает mycls объект для каждого вызова 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

Если вы перемещаете операторы 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 относится к mycls возразите что оператор myobj = mycls создает. Этот оператор создает mycls объект для каждого вызова 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

Если вы делаете 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 это копирует свойство объекта указателя в другой объект. Функция использует простой класс Handle и класс значения. В 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.

Три переменные ссылаются на ту же ячейку памяти: xY, и v.prop. Генератор кода определяет тот x.prop и y.prop совместно используйте то же значение. Генератор кода не может решить что свойство объекта указателя v.prop.prop совместно использует его определение с x.prop и y.prop. Чтобы избежать ошибки, задайте v.prop.prop непосредственно.