Skip to main content

Konstantenpropagation

Mit der CODESYS Static Analysis Version V5.0.0.0 basiert die statische Codeanalyse auf Konstantenpropagation. Die Ergebnisse der Konstantenpropagation werden für verschiedene Überprüfungen genutzt. So wird beispielsweise überprüft, ob Pointer ungleich 0 sind, oder ob Arrayindindizes außerhalb des gültigen Bereichs liegen.

Sie können die statische Analyse effektiv unterstützen, allein wenn sie wissen, wie diese Analyse funktioniert und wo ihre Grenzen liegen.

Konstantenpropagation

Bei der statischen Analyse wird versucht, den Wert einer Variable anhand ihrer Verwendung zu bestimmen.

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

In der Implementierung in Zeile 1 zeichnet die Konstantenpropagation den Wert 99 für die Variable x , um diesen Wert für weitere Analysen zu verwenden. Die Analyse erkennt dann, dass der Ausdruck in der nachfolgenden IF-Anweisung konstant TRUE ist.



Lokal durchgeführte Konstantenpropagation

Ein Wert wird nur lokal im Baustein ermittelt. Es ist unerheblich, wie eine Eingabe übergeben wird. Auch die Ergebnisse von Funktionsaufrufen sind irrelevant.

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


Wenn der Parameter bTest bei jedem Aufruf auf TRUE gesetzt wird, hat dies keine Auswirkung auf die Konstantenpropagation. Auch wenn OtherFunc(TRUE) immer TRUE zurück gibt, hat dies keine Auswirkung auf die Konstantenpropagation.

Nur temporäre Variablen haben Initialwerte

Statische lokale Variablen in Programmen und Funktionsbausteinen haben keinen angenommenen Initialwert. Die Variablen behalten ihre Werte vom letzten Aufruf und können daher prinzipiell "alles" sein.

Lokale Variablen in Funktionen und temporäre Variablen haben einen Initialwert bei jedem Aufruf. Die Konstantenpropagation rechnet mit diesem Initialwert.

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

Die Variable y wird bei jeder Ausführung von PLC_PRG den Wert 8 haben. Die Variable x jedoch nicht unbedingt. Daher wird die Konstantenpropagation nur für y einen Wert annehmen, nicht aber für x.

Es empfiehlt sich, Variablen, die immer zuerst geschrieben und dann gelesen werden, als temporäre Variablen zu deklarieren.



Konstantenpropagation ermittelt Wertebereiche für numerische Datentypen

Um die Komplexität zu reduzieren, wird für jede Variable ein Wertebereich mit Ober- und Untergrenze ermittelt.

Beispiel 4. Beispiel
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

Hier wird für die Variable x der Wertebereich [1..100] ermittelt. Infolgedessen wird in Zeile 7 der Vergleich x = 77 nicht als konstanter Ausdruck erkannt, da 77 innerhalb des Wertebereichs liegt.



Wiederkehrende komplexe Ausdrücke werden nicht als die gleiche Variable erkannt

Komplexe Ausdrücke haben unter Umständen keinen Wert zugeordnet. Wenn solche Ausdrücke mehrfach vorkommen, ist es hilfreich, eine Hilfsvariable einzuführen.

Beispiel 5. Beispiel
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

In Zeile 2 wird ein Fehler ausgegeben für einen möglichen Zugriff über Pointer auf einen Wert, obwohl der Bereich, auf den der Pointer zeigt, überprüft wird. Wird der Wert zuerst in eine lokale Variable kopiert und deren Bereich überprüft, dann kann die Konstantenpropagation den Wertebereich für diese Variable ermitteln und erlaubt den Zugriff in den Array in Zeile 7.



Verzweigungen

Bei Verzweigungen werden einzelne Zweige getrennt berechnet. Wertebereiche aus den einzelnen Bereichen werden anschließend zu einem neuen Wertebereich vereinigt.

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

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

In Zeile 6 hat x den Bereich [1..10]. Nach Zeile 11 hat y den Wertebereich [1..20], das ergibt sich aus der Vereinigung der beiden Wertebereiche [1..10] und [2..20].



Bedingungen

Beispiel 7. Beispiel

Bedingungen können den Wertebereich einer Variablen in einem Codeblock einschränken. Mehrere Bedingungen können kombiniert werden. Einander ausschließende Bedingungen können auch zu einem leeren Wertebereich führen.

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

y hat in Zeile 2 den Wertebereich [1..9]. Daraus ergibt sich für x in Zeile 6 der Wertebereich [0..9] . Kombiniert mit der Bedingung x < 0 ergibt das in Zeile 8 für x eine leere Menge an möglichen Werten. Der Code ist nicht erreichbar. Die statische Analyse wird melden, dass die Bedingung x < 0 an dieser Stelle immer FALSE ergibt.



Schleifen

Die Konstantenpropagation wird Schleifen im Code so lange ausführen, bis sich die Werte der Variablen in der Schleife nicht mehr ändern. Dabei wird angenommen, dass eine Schleife beliebig oft durchlaufen werden kann. Die bisher ermittelten Werte werden mit den vorhergehenden Werten vereint. Variablen, die innerhalb der Schleife geändert werden, haben einen sukzessiv wachsenden Bereich. Dabei nimmt die Konstantenpropagation nicht alle möglichen Werte für Bereiche an, sondern verwendet nur im Code vorkommende Grenzen und außerdem die Werte 0, 1, 2, 3 und 10, da diese häufig eine Rolle spielen.

Beispiel 8. Beispiel

Am einfachsten wird das Vorgehen an einem Beispiel deutlich:

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

Die Konstantenpropagation weiß folgendes über die Schleife:

i, x, und y sind zu Beginn der ersten Ausführung der Schleife 0. Für den Code in der Schleife gilt die Bedingung i <= 5. Für den Code nach der Schleife gilt die Bedingung i > 5.

Für die Werte der Variablen in der Schleife ermittelt die Konstantenpropagation folgende Werte:

i

x

y

[0..5]

[0..MAXDINT]

[0..5]

Im Detail werden folgende Zwischenschritte durchlaufen:

Durchlauf

i

x

y

1

0

[0..1]

0

i wurde mit 0 initialisiert, y bekommt immer die gleichen Werte wie i

2

[0..1]

[0..2]

[0..1]

6

[0..5]

[0..6]

[0..5]

Zunächst wird tatsächlich der Bereich [0..6] für i berechnet. Es ist aber bekannt, dass i < 5 eine Bedingung ist. Daher wird der Wert für den Code in der Schleife auf diesen Wert begrenzt.

7

[0..5]

[0..7]

[0..5]

10

[0..5]

[0..10]

[0..5]

x wird immer weiter hochgezählt. Ab 10 wird allerdings der Wert auf MAXINT "aufgerundet".

11

[0..5]

[0..MAXDINT]

[0..5]

MAXDINT + 1 ergibt MAXDINT

ab 11

Ab dem 11. Durchlauf werden sich die Werte in der Schleife nicht mehr ändern. Die Propagation wird beendet.

Darüber hinaus gilt für den nach dieser Schleife folgenden Code i = 6. Es wird in der Schleife der Bereich [0..6] ermittelt und dieser mit der Bedingung i > 5 kombiniert, was exakt den Wert 6 ergibt.