不断传播
随着 CODESYS Static Analysis 版本V5.0.0.0,代码的分析基于常量传播。恒定传播的结果用于各种检查。例如,它检查指针是否不等于 0,或者数组索引是否超出有效范围。
只需了解静态分析的工作原理及其局限性,您就可以有效地支持静态分析。
不断传播
静态分析尝试根据变量的用途来确定变量的值。
PROGRAM PLC_PRG
//Declaration
VAR
x: INT;
bTest: BOOL;
END_VAR//Implementation
x := 99;
IF x < 100 THEN
bTest := TRUE;
END_IF在第 1 行的实现中,常量传播记录了值 99 对于变量 x 使用该值进行进一步分析。然后分析发现以下表达式 IF- 语句常量 TRUE 是。
局部执行恒定传播
仅在功能块中本地确定值。输入的传递方式无关紧要。函数调用的结果也是无关紧要的。
FUNCTION Func : BOOL
//Declaration
VAR_INPUT
bText : BOOL;
END_VAR//Implementation
IF bTest THEN
Func := OtherFunc(TRUE);
END_IF即使参数 bTest 被设定为 TRUE 在每次调用时,这对恒定传播没有影响。即使 OtherFunc(TRUE) 总是返回 TRUE,这对恒定传播没有影响。
只有临时变量才有初始值。
程序和功能块中的静态局部变量没有假定的初始值。这些变量保留上次调用时的值,因此原则上可以是“任何值”。
函数中的局部变量和临时变量在每次调用时都有一个初始值。常数传播用这个初始值进行计算。
PROGRAM PLC_PRG
//Declaration
VAR
x: INT := 6;
bTest: BOOL;
END_VAR
VAR_TEMP
y : INT := 8;
END_VARbText := x < y;
变量 y 每次都会被执行 PLC_PRG 值为 8。变量 x但也不一定。因此,恒定传播仅用于 y 假设一个值,但不是为了 x。
建议声明始终先写入然后读取的变量作为临时变量。
常数传播确定数值数据类型的值范围。
为了降低复杂性,为每个变量确定了具有上限和下限的值范围。
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这里取值范围 [1..100] 是为变量确定的 x。结果,在第 7 行,比较 x = 77 不被识别为常量表达式,因为 77 是在数值范围之内。
重复出现的复杂表达式不会被识别为同一变量。
复杂表达式可能没有分配值。如果这样的表达式多次出现,那么引入辅助变量会很有帮助。
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在第 2 行,尽管检查了指针指向的区域,但由于可能通过指针访问某个值,因此会发出错误。如果首先将该值复制到局部变量中并检查其范围,则常量传播可以确定该变量的值范围,并允许访问第 7 行的数组。
分枝
对于分支,单独计算各个分支。然后将各个范围中的值范围组合起来形成新的值范围。
//Implementation
IF func(TRUE) THEN
x := 1;
ELSE
x := 10;
END_IF
IF func(FALSE) THEN
y := x;
ELSE
Y := 2*x;
END_IF6号线, x 有范围 [1..10]。第 11 行之后, y 有取值范围 [1..20];这是两个值范围并集的结果 [1..10] 和 [2..20]。
状况
条件可以限制代码块中变量的值范围。可以组合多个条件。互斥条件也可能导致空值范围。
IF y > 0 AND y < 10 THEN
x := y;
ELSE
x:= 0;
END_IF
IF x < 0 THEN
i := 99;
END_IFy 的取值范围 [1..9] 第 2 行。这会得出值范围 [0..9] 为了 x 第6行。结合条件 x < 0,这会导致一组空的可能值 x 第 8 行。该代码无法访问。静态分析将报告该情况 x < 0 总是返回 FALSE 在此刻。
循环播放
常量传播将循环代码,直到循环中变量的值不再改变。假设循环可以运行任意次。到目前为止确定的值与之前的值相结合。在循环内改变的变量具有连续增长的范围。这里,常数传播并不采用所有可能的范围值,而是仅使用代码中出现的限制以及值 0、1、2、3 和 10,因为这些通常是相关的。
描述该过程的最简单方法是通过示例:
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常量传播了解有关循环的以下信息:
i, x, 和 y 在第一次执行循环开始时为 0。条件 i <= 5 适用于循环中的代码。条件 i > 5 适用于循环后的代码。
对于循环中变量的值,常数传播确定以下值:
|
|
| ||
|---|---|---|---|---|
|
|
|
具体来说,经过以下中间步骤:
经过 |
|
|
| |
|---|---|---|---|---|
1 | 0 |
|
|
|
2 |
|
|
| |
6 |
|
|
| 一、范围 |
7 |
|
|
| |
10 |
|
|
|
|
11 |
|
|
|
|
截至11日 | 从第11遍开始,循环中的值不会改变。传播结束。 |
此外, i = 6 适用于该循环之后的代码。范围 [0..6] 在循环中确定,并与条件结合 i > 5,结果恰好是值 6。