Не удается определить, что каждый элемент массива ячеек назначен

Проблема

Вы видите одно из следующих сообщений:

Unable to determine that every element of 'y' is
assigned before this line.
Unable to determine that every element of 'y' is
assigned before exiting the function.
Unable to determine that every element of 'y' is
assigned before exiting the recursively called function.

Причина

Для генерации кода, прежде чем вы используете элемент массива ячеек, вы должны назначить ему значение. Когда вы используете cell чтобы создать массив ячеек переменного размера, например cell(1,n), MATLAB® присваивает пустую матрицу каждому элементу. Однако для генерации кода элементы не назначены. Для генерации кода, после того, как вы используете cell чтобы создать массив ячеек переменного размера, необходимо назначить все элементы массива ячеек перед любым использованием массива ячеек.

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

function z = CellVarSize1D(n, j)
%#codegen
x = cell(1,n);   
for i = 1:n
    x{i} = i;
end
z = x{j};
end

Вот шаблон для многомерного массива ячеек:

function z = CellAssign3D(m,n,p)
%#codegen
x = cell(m,n,p);
for i = 1:m
    for j =1:n
        for k = 1:p
            x{i,j,k} = i+j+k;
        end
    end
end
z = x{m,n,p};
end

Если генератор кода обнаруживает, что некоторые элементы не назначены, генерация кода прекращает работать. Иногда, даже если ваш код присваивает все элементы массива ячеек, генерация кода прекращает работать, поскольку анализ не обнаруживает, что все элементы назначены.

Вот примеры, где генератор кода не может обнаружить, что элементы назначены:

  • Элементы назначаются в разных циклах

    ...
    x = cell(1,n)
    for i = 1:5
        x{i} = 5;
    end
    for i = 6:n
        x{i} = 7;
    end 
    ...             

  • Переменная, которая задает значение конца цикла, не совпадает с переменной, которая задает размерность камеры.

    ...
    x = cell(1,n);
    m = n;
    for i = 1:m
        x{i} = 2;
    end 
    ...                 

Для получения дополнительной информации смотрите Определение массива ячеек переменного размера при помощи камеры.

Решение

Попробуйте одно из следующих решений:

Используйте распознанный шаблон для назначения элементов

Если возможно, перепишите код, чтобы следовать этому шаблону:

...
x = cell(1,n);   
for i = 1:n
    x{i} = i;
end
z = x{j};
...

Использовать repmat

Иногда можно использовать repmat для определения массива ячеек переменного размера.

Рассмотрим этот код, который задает массив ячеек переменного размера. Значение 1 присваивается нечетным элементам, а значение 2 - четным элементам.

function z = repDefine(n, j)
%#codegen
c =cell(1,n);
for i = 1:2:n-1
    c{i} = 1;
end
for i = 2:2:n
    c{i} = 2;
end
z = c{j};

Генерация кода не позволяет использовать этот код, поскольку:

  • Элементы присваиваются более чем одному циклу.

  • Счетчик цикла не увеличивается на 1.

Перепишите код для первого использования cell создать массив ячеек 1 на 2, первый элемент которого равен 1, а второй элемент равен 2. Затем используйте repmat чтобы создать массив ячеек переменного размера, значения элемента которого чередуются между 1 и 2.

function z = repVarSize(n, j)
%#codegen
c = cell(1,2);
c{1} = 1;
c{2} = 2;
c1= repmat(c,1,n);
z = c1{j};
end

Можно передать первоначально пустой массив ячеек переменного размера в функцию или из нее при помощи repmat. Используйте следующий шаблон:

function x = emptyVarSizeCellArray
x = repmat({'abc'},0,0);
coder.varsize('x');
end

Этот код указывает, что x - пустой массив ячеек переменного размера 1x3 символы, которые могут быть переданы в функции или из них.

Использовать coder.nullcopy

В крайнем случае можно использовать coder.nullcopy чтобы указать, что генератор кода может выделить память для массива ячеек, не инициализируя память. Для примера:

function z = nulcpyCell(n, j)
%#codegen
c =cell(1,n);
c1 = coder.nullcopy(c);
for i = 1:4
    c1{i} = 1;
end
for i = 5:n
    c1{i} = 2;
end
z = c1{j};
end

Использовать coder.nullcopy с осторожностью. Если вы получаете доступ к неинициализированной памяти, результаты непредсказуемы.

См. также

| |

Похожие темы