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.
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.
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.
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.
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.
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.
//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
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.
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:
|
|
| ||
---|---|---|---|---|
|
|
|
Im Detail werden folgende Zwischenschritte durchlaufen:
Durchlauf |
|
|
| |
---|---|---|---|---|
1 | 0 |
|
|
|
2 |
|
|
| |
6 |
|
|
| Zunächst wird tatsächlich der Bereich |
7 |
|
|
| |
10 |
|
|
|
|
11 |
|
|
|
|
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.