Skip to main content

Propagation constante

Avec le CODESYS Static Analysis version V5.0.0.0, l'analyse du code est basée sur une propagation constante. Les résultats de propagation constante sont utilisés pour divers contrôles. Par exemple, il vérifie si les pointeurs ne sont pas égaux à 0 ou si les indices de tableau sont hors plage valide.

Vous pouvez prendre en charge efficacement l'analyse statique simplement en sachant comment cette analyse fonctionne et quelles sont ses limites.

Propagation constante

L'analyse statique tente de déterminer la valeur d'une variable en fonction de son utilisation.

Exemple 1. Exemple
PROGRAM PLC_PRG
//Declaration
VAR
    x: INT;
    bTest: BOOL;
END_VAR
//Implementation
x := 99;
IF x < 100 THEN
    bTest := TRUE;
END_IF

Dans l'implémentation de la ligne 1, la propagation constante enregistre la valeur 99 pour la variable x pour utiliser cette valeur pour une analyse plus approfondie. L’analyse reconnaît alors que l’expression suivante IF-Constante de déclaration TRUE est.



Propagation constante effectuée localement

Une valeur est déterminée uniquement localement dans le bloc fonctionnel. La manière dont une entrée est transmise n'a pas d'importance. Les résultats des appels de fonction ne sont pas non plus pertinents.

Exemple 2. Exemple
FUNCTION Func : BOOL
//Declaration
VAR_INPUT
    bText : BOOL;
END_VAR
//Implementation
IF bTest THEN
    Func := OtherFunc(TRUE);
END_IF


Même si le paramètre bTest est réglé sur TRUE à chaque appel, cela n'a aucun effet sur la propagation constante. Même si OtherFunc(TRUE) revient toujours TRUE, cela n'a aucun effet sur la propagation constante.

Seules les variables temporaires ont des valeurs initiales.

Les variables locales statiques dans les programmes et les blocs fonctionnels n'ont pas de valeur initiale supposée. Les variables conservent leurs valeurs du dernier appel et peuvent donc en principe être "n'importe quoi".

Les variables locales dans les fonctions et les variables temporaires ont une valeur initiale à chaque appel. La propagation constante est calculée avec cette valeur initiale.

Exemple 3. Exemple
PROGRAM PLC_PRG
//Declaration
VAR
    x: INT := 6;
    bTest: BOOL;
END_VAR
VAR_TEMP
    y : INT := 8;
END_VAR
bText := x < y;

La variable y est exécuté à chaque fois PLC_PRG ont la valeur 8. La variable x mais pas nécessairement. Par conséquent, la propagation constante n’est utilisée que pour y prendre une valeur, mais pas pour x.

Il est recommandé de déclarer des variables qui sont toujours écrites en premier puis lues comme variables temporaires.



La propagation constante détermine des plages de valeurs pour les types de données numériques.

Pour réduire la complexité, une plage de valeurs avec des limites supérieure et inférieure est déterminée pour chaque variable.

Exemple 4. Exemple
PROGRAM PLC_PRG
VAR
    x: INT := 6;
    bTest: BOOL;
    y : INT;    
END_VAR
//Implementation
IF bTest THEN
    x := 1;
ELSSE
    x := 100;
END_IF
IF x = 77 THEN
    y := 13;
END_IF

Ici la plage de valeurs [1..100] est déterminé pour la variable x. En conséquence, à la ligne 7, la comparaison x = 77 n'est pas reconnu comme une expression constante car 77 est dans la plage de valeurs.



Les expressions complexes récurrentes ne sont pas reconnues comme la même variable.

Les expressions complexes ne peuvent pas avoir de valeur attribuée. Si de telles expressions apparaissent plusieurs fois, il est alors utile d’introduire une variable auxiliaire.

Exemple 5. Exemple
PROGRAM PLC_PRG
VAR
    x: DINT;
    py : POINTER TO INT;
    y : INT; 
    testArray : ARRAY [0..4] OF DINT;   
END_VAR
//Implementation
IF py^ >= 0 AND py^<= 4 THEN
    x := testArray[py^];
END_IF
y := py^;
IF y <= 0 AND y <=4 THEN
    x := testArray[y];
END_IF

A la ligne 2, une erreur est émise pour un éventuel accès via pointeur à une valeur, bien que la zone pointée par le pointeur soit vérifiée. Si la valeur est d'abord copiée dans une variable locale et que sa plage est vérifiée, alors la propagation constante peut déterminer la plage de valeurs pour cette variable et permettre l'accès au tableau sur la ligne 7.



Ramification

Pour le branchement, les branches individuelles sont calculées séparément. Les plages de valeurs des différentes plages sont ensuite combinées pour former une nouvelle plage de valeurs.

Exemple 6. Exemple
//Implementation
IF func(TRUE) THEN
    x := 1;
ELSE 
    x := 10;
END_IF

IF func(FALSE) THEN
    y := x;
ELSE
    Y := 2*x;
END_IF

Sur la ligne 6, x a la portée [1..10]. Après la ligne 11, y a la plage de valeurs [1..20]; cela résulte de l'union des deux plages de valeurs [1..10] et [2..20].



Conditions

Exemple 7. Exemple

Les conditions peuvent restreindre la plage de valeurs d'une variable dans un bloc de code. Plusieurs conditions peuvent être combinées. Des conditions mutuellement exclusives peuvent également donner lieu à une plage de valeurs vide.

IF y > 0 AND y < 10 THEN
    x := y;
ELSE
    x:= 0;
END_IF
IF x < 0 THEN
    i := 99;
END_IF

y a la plage de valeurs [1..9] à la ligne 2. Cela donne la plage de valeurs [0..9] pour x à la ligne 6. Combiné avec la condition x < 0, cela donne un ensemble vide de valeurs possibles pour x à la ligne 8. Le code n'est pas accessible. L'analyse statique indiquera que la condition x < 0 revient toujours FALSE à ce point.



Boucle

Une propagation constante bouclera le code jusqu'à ce que les valeurs des variables dans la boucle ne changent plus. On suppose qu’une boucle peut être exécutée un nombre illimité de fois. Les valeurs déterminées jusqu'à présent sont combinées avec les valeurs précédentes. Les variables modifiées dans la boucle ont une plage croissante. Ici, la propagation constante ne prend pas toutes les valeurs possibles pour les plages, mais utilise uniquement les limites qui apparaissent dans le code ainsi que les valeurs 0, 1, 2, 3 et 10 car celles-ci sont souvent pertinentes.

Exemple 8. Exemple

La façon la plus simple de décrire la procédure est de prendre un exemple :

PROGRAM PLC_PRG
VAR
    x: DINT;
    i : DINT;
    y : DINT;
END_VAR
//Implementation
x := 0;
y := 0;
FOR i := 0 TO 5 DO
    x := x + 1;
    y := i;
END_FOR

La propagation constante connaît les éléments suivants à propos de la boucle :

i, x, et y valent 0 au début de la première exécution de la boucle. La condition i <= 5 s'applique au code dans la boucle. La condition i > 5 s'applique au code après la boucle.

Pour les valeurs des variables dans la boucle, la propagation constante détermine les valeurs suivantes :

i

x

y

[0..5]

[0..MAXDINT]

[0..5]

Dans le détail, les étapes intermédiaires suivantes sont parcourues :

Passer

i

x

y

1

0

[0..1]

0

i a été initialisé à 0 ; y obtient toujours les mêmes valeurs que i.

2

[0..1]

[0..2]

[0..1]

6

[0..5]

[0..6]

[0..5]

Tout d'abord, la gamme [0..6] est en fait calculé pour i. Or, on sait que i < 5 est une condition. Par conséquent, la valeur du code dans la boucle est limitée à cette valeur.

7

[0..5]

[0..7]

[0..5]

10

[0..5]

[0..10]

[0..5]

x s'accroît de plus en plus. Depuis 10, cependant, la valeur est « arrondie » à MAXINT.

11

[0..5]

[0..MAXDINT]

[0..5]

MAXDINT + 1 résulte en MAXDINT

Dès le 11

A partir du 11ème passage, les valeurs dans la boucle ne changeront pas. La propagation est terminée.

En outre, i = 6 s'applique au code suivant cette boucle. La gamme [0..6] est déterminé dans la boucle et ceci est combiné avec la condition i > 5, ce qui donne exactement la valeur 6.