La traduction de cette page n'est pas à jour. Cliquez ici pour voir la dernière version en anglais.
Résoudre le problème : les variables doivent être entièrement définies avant utilisation
Problème
Contrairement à MATLAB® qui est un langage à typage dynamique, le C et le C++ ont un typage statique. Cela signifie que le générateur de code doit être en mesure de déterminer le type de toutes les variables de votre code MATLAB pour définir et allouer des variables dans le code généré. Si le générateur de code ne parvient pas à déterminer le type d’une ou plusieurs variables dans votre code MATLAB, il renvoie un message d’erreur contenant la phrase suivante :
For code generation, all variables must be fully defined before use.
Si le message d’erreur affiché concerne un cell array ou un élément de cell array, consultez Resolve Issue: Cell Array Elements Must Be Fully Defined Before Use.
Solutions possibles
Pour résoudre ce problème, affectez des valeurs à toutes les variables de votre code MATLAB sur tous les chemins d’exécution. Cela comprend toutes les variables figurant dans d’autres structures de données telles que les champs de structure et les propriétés de classe. Essayez l’une des solutions suivantes en fonction de votre code MATLAB et du message d’erreur spécifique qui s’affiche.
Affecter des valeurs aux variables sur tous les chemins d’exécution
Dans certains cas, le générateur de code ne parvient pas à déterminer que toutes les variables sont définies sur tous les chemins d’exécution. Par exemple, créez une fonction MATLAB undefinedVariableTest qui reçoit une entrée numérique x et renvoie la valeur absolue de x.
function y = undefinedVariableTest(x) %#codegen arguments x (1,1) double end if x == 0 y = 0; elseif x < 0 y = -x; elseif x > 0 y = x; end end
undefinedVariableTest renvoient une valeur pour toutes les valeurs de x. Toutefois, la génération de code échoue pour undefinedVariableTest, car le générateur de code ne trouve pas d’instruction else et ne peut donc pas déterminer que y est défini sur tous les chemins d’exécution possibles.Pour que ce code convienne pour la génération de code, obligez le générateur de code à détecter que y est défini sur tous les chemins d’exécution possibles en utilisant une instruction else.
function y = undefinedVariableTest(x) %#codegen arguments x (1,1) double end if x == 0 y = 0; elseif x < 0 y = -x; else y = x; end end
Une autre solution consiste à affecter une valeur fictive à y en dehors de l’instruction if.
function y = undefinedVariableTest(x) %#codegen arguments x (1,1) double end y = 0; if x == 0 y = 0; elseif x < 0 y = -x; elseif x > 0 y = x; end end
Affecter des valeurs à tous les champs de structure et propriétés de classe
Vous devez définir toutes les variables contenues dans d’autres types de données sur tous les chemins d’exécution. Vous ne pouvez pas modifier le nombre ni le format des champs de structure ou des propriétés de classe une fois que la structure ou la classe a été utilisée. En outre, pour certains patterns de codage, le générateur de code n’est pas en mesure de détecter que toutes les variables contenues dans un autre type de données sont définies. Dans ces situations, essayez de réécrire votre code avec un pattern de codage différent.
Champs de structure. Dans le code MATLAB destiné à la génération de code, vous ne pouvez pas ajouter de champs à une structure une fois que vous l’avez lue, indexée ou passée à une fonction. Par exemple, créez une fonction MATLAB undefinedFieldTest qui renvoie une structure y. Si x est supérieur à 10, undefinedFieldTest définit et affecte une valeur au champ field1 de la structure s. Sinon, undefinedFieldTest définit et affecte des valeurs aux champs field1 et field2 de la structure s.
function y = undefinedFieldTest(x) %#codegen arguments x (1,1) double end if x > 10 s.field1 = 11; else s.field1 = 12; s.field2 = 12; end y = s; end
field2 est ajouté de manière dynamique à la structure s si x est inférieur ou égal à 10. Cependant, le générateur de code doit déterminer le type de tous les champs contenus dans la structure s au moment de la génération du code alors que la valeur run-time de x est inconnue. La génération de code échoue, car le générateur de code détecte que le champ field2 fait partie de la structure s sur certains chemins d’exécution mais pas sur d’autres.Pour que ce code convienne pour la génération de code, ne modifiez pas le nombre ni le nom des champs contenus dans une structure au run-time. Définissez tous les champs de s indépendamment de la valeur run-time de x.
function y = undefinedFieldTest(x) %#codegen arguments x (1,1) double end s = struct("field1", [], "field2", []); if x > 10 s.field1 = 11; else s.field1 = 12; s.field2 = 12; end y = s; end
Propriétés de classe. Pour certains patterns de codage où vous affectez des valeurs à des propriétés de classe dans une boucle, le générateur de code n’est pas en mesure de détecter que toutes les propriétés sont définies. Par exemple, créez une fonction MATLAB undefinedPropTest qui reçoit un entier positif n en entrée et renvoie une instance de la classe MyClass. La classe MyClass a deux propriétés prop1 et prop2. La fonction undefinedPropTest affecte des valeurs à prop1 et prop2 pour l’objet myClass renvoyé dans une boucle for.
function y = undefinedPropTest(n) %#codegen arguments n (1,1) double {mustBePositive, mustBeInteger} end x = MyClass; for i = 1:n x.prop1 = 1 + i; x.prop2 = x.prop1 + 3; end y = x; end
undefinedPropTest renvoie une instance de MyClass pour toutes les valeurs autorisées de n. Toutefois, la génération de code pour undefinedPropTest échoue, car le générateur de code ne peut pas déterminer que undefinedPropTest affecte des valeurs à prop1 et prop2 pour toutes les valeurs de n.Pour que ce code convienne pour la génération de code, affectez des valeurs fictives à toutes les propriétés de MyClass avant la boucle for.
function y = undefinedPropTest(n) %#codegen arguments n (1,1) double {mustBePositive, mustBeInteger} end x = MyClass; x.prop1 = 0; x.prop2 = 0; for i = 1:n x.prop1 = 1 + i; x.prop2 = x.prop1 + 3; end y = x; end
Affecter des valeurs initiales à toutes les variables persistantes
Vous devez définir toutes les variables persistent de votre code MATLAB sur tous les chemins d’exécution. Par exemple, créez une fonction MATLAB undefinedPersistentTest qui stocke le nombre de fois où elle a été appelée dans la variable persistent nommée count. Pour initialiser ou réinitialiser count, undefinedPersistentTest doit être appelée avec l’argument 0.
function y = undefinedPersistentTest(x) persistent count; if x == 0 count = 0; else count = count + 1; end y = count; end
MATLAB définit automatiquement une variable persistante égale à une matrice vide ([]) à la première occurrence. Par conséquent, les appels de undefinedPersistentTest ne produisent aucune erreur même si une valeur a été affectée à count. Toutefois, le générateur de code ne peut pas déterminer la taille et le type d’une variable persistante non initialisée au moment de la génération du code. Par conséquent, la génération de code pour undefinedPersistentTest échoue, car count n’est pas défini pour toutes les valeurs de x.
Pour que ce code convienne pour la génération de code, utilisez la fonction isempty pour affecter une valeur à count si cette variable n’est pas définie.
function y = undefinedPersistentTest(x) arguments x (1,1) double end persistent count; if isempty(count) count = 0; end if x == 0 count = 0; else count = count + 1; end y = count; end
Définir les variables sans affectation
Dans certaines situations, la définition des variables par affectation dans le code généré représente une surcharge importante. Elle peut également entraîner l’apparition de copies redondantes des variables dans le code généré. Pour définir le type, la taille et la complexité des variables sans la surcharge associée à leur affectation, utilisez coder.nullcopy.
L’utilisation de coder.nullcopy pour définir une variable vous permet de générer le code sans avoir à respecter les patterns de codage décrits ci-dessus. Prenons l’exemple de la fonction nullcopyExample. Comme elle utilise coder.nullcopy pour préallouer de la mémoire pour la classe MyClass, vous n’avez pas besoin d’affecter des valeurs fictives aux propriétés de cette classe.
function y = nullcopyExample(n) %#codegen arguments n (1,1) double {mustBePositive, mustBeInteger} end x = coder.nullcopy(MyClass); for i = 1:n x.prop1 = 1 + i; x.prop2 = x.prop1 + 3; end y = x; end
Remarque
Utilisez coder.nullcopy avec prudence. Veillez à affecter des valeurs à toutes les variables, y compris les propriétés de classe, les champs de structure et les éléments de tableau. L’accès à des variables non initialisées peut produire des résultats imprévisibles.