Propagación constante
Con el CODESYS Static Analysis versión V5.0.0.0, el análisis del código se basa en la propagación constante. Los resultados de la propagación constante se utilizan para diversas comprobaciones. Por ejemplo, comprueba si los punteros no son iguales a 0 o si los índices de la matriz están fuera del rango válido.
Puede respaldar eficazmente el análisis estático con solo saber cómo funciona este análisis y cuáles son sus limitaciones.
Propagación constante
El análisis estático intenta determinar el valor de una variable en función de su uso.
PROGRAM PLC_PRG //Declaration VAR x: INT; bTest: BOOL; END_VAR
//Implementation x := 99; IF x < 100 THEN bTest := TRUE; END_IF
En la implementación en la línea 1, la propagación constante registra el valor 99
para la variable x
utilizar este valor para análisis posteriores. El análisis luego reconoce que la expresión en el siguiente IF
-Declaración constante TRUE
es.
Propagación constante realizada localmente
Un valor se determina sólo localmente en el bloque de funciones. Es irrelevante cómo se pasa una entrada. Los resultados de las llamadas a funciones también son irrelevantes.
FUNCTION Func : BOOL //Declaration VAR_INPUT bText : BOOL; END_VAR
//Implementation IF bTest THEN Func := OtherFunc(TRUE); END_IF
Incluso si el parámetro bTest
se establece en TRUE
en cada llamada, esto no tiene ningún efecto sobre la propagación constante. Incluso si OtherFunc(TRUE)
siempre regresa TRUE
, esto no tiene ningún efecto sobre la propagación constante.
Sólo las variables temporales tienen valores iniciales.
Las variables locales estáticas en programas y bloques de funciones no asumen ningún valor inicial. Las variables conservan sus valores de la última llamada y, por lo tanto, en principio pueden ser "cualquier cosa".
Las variables locales en funciones y las variables temporales tienen un valor inicial en cada llamada. La propagación constante se calcula con este valor inicial.
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
se ejecuta cada vez PLC_PRG
tiene el valor 8. La variable x
, sin embargo, no necesariamente. Por lo tanto, la propagación constante sólo se utiliza para y
asumir un valor, pero no por x
.
Se recomienda declarar variables que siempre se escriben primero y luego se leen como variables temporales.
La propagación constante determina rangos de valores para tipos de datos numéricos.
Para reducir la complejidad, se determina un rango de valores con límites superior e inferior para cada variable.
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
Aquí el rango de valores. [1..100]
se determina para la variable x
. Como resultado, en la línea 7, la comparación x = 77
no se reconoce como una expresión constante porque 77
está dentro del rango de valores.
Las expresiones complejas recurrentes no se reconocen como la misma variable.
Es posible que las expresiones complejas no tengan un valor asignado. Si este tipo de expresiones aparecen varias veces, resulta útil introducir una variable auxiliar.
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
En la línea 2 se emite error por un posible acceso mediante puntero a un valor, aunque se comprueba la zona a la que apunta el puntero. Si el valor se copia primero en una variable local y se verifica su rango, entonces la propagación constante puede determinar el rango de valores para esa variable y permite el acceso a la matriz en la línea 7.
Derivación
Para las bifurcaciones, las ramas individuales se calculan por separado. A continuación, los rangos de valores de los rangos individuales se combinan para formar un nuevo rango de valores.
//Implementation IF func(TRUE) THEN x := 1; ELSE x := 10; END_IF IF func(FALSE) THEN y := x; ELSE Y := 2*x; END_IF
En la línea 6, x
tiene el rango [1..10]
. Después de la línea 11, y
tiene el rango de valores [1..20]
; esto resulta de la unión de los dos rangos de valores [1..10]
y [2..20]
.
Condiciones
Las condiciones pueden restringir el rango de valores de una variable en un bloque de código. Se pueden combinar varias condiciones. Las condiciones mutuamente excluyentes también pueden dar como resultado un rango de valores vacío.
IF y > 0 AND y < 10 THEN x := y; ELSE x:= 0; END_IF IF x < 0 THEN i := 99; END_IF
y tiene el rango de valores [1..9]
en la línea 2. Esto da como resultado el rango de valores [0..9]
para x
en la línea 6. Combinado con la condición x < 0
, esto da como resultado un conjunto vacío de valores posibles para x
en la línea 8. No se puede acceder al código. El análisis estático informará que la condición x < 0
siempre regresa FALSE
en este punto.
Bucle
La propagación constante hará un bucle en el código hasta que los valores de las variables en el bucle ya no cambien. Se supone que un bucle se puede ejecutar cualquier número de veces. Los valores determinados hasta ahora se combinan con los valores anteriores. Las variables que se modifican dentro del bucle tienen un rango cada vez mayor. Aquí, la propagación constante no toma todos los valores posibles para los rangos, sino que utiliza sólo los límites que aparecen en el código y también los valores 0, 1, 2, 3 y 10 porque suelen ser relevantes.
La forma más sencilla de describir el procedimiento es con el ejemplo:
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 propagación constante sabe lo siguiente sobre el bucle:
i
, x
, y y
son 0 al comienzo de la primera ejecución del bucle. La condición i <= 5
se aplica al código en el bucle. La condición i > 5
se aplica al código después del bucle.
Para los valores de las variables en el bucle, la propagación constante determina los siguientes valores:
|
|
| ||
---|---|---|---|---|
|
|
|
En detalle, se pasan por los siguientes pasos intermedios:
Aprobar |
|
|
| |
---|---|---|---|---|
1 | 0 |
|
|
|
2 |
|
|
| |
6 |
|
|
| Primero, el rango |
7 |
|
|
| |
10 |
|
|
|
|
11 |
|
|
|
|
A partir de las 11 | A partir del undécimo pase, los valores en el bucle no cambiarán. La propagación ha terminado. |
Además, i = 6
se aplica al código que sigue a este bucle. El rango [0..6]
se determina en el bucle y esto se combina con la condición i > 5
, lo que da como resultado exactamente el valor 6.