SA0011:只有一个成员的无用声明 检测仅具有单个成员的结构或枚举 理由:不应声明只有一个成员的结构或枚举。此类声明可能会让读者感到困惑。只有一个元素的结构可以用别名类型替换。只有一个元素的枚举可以用常量替换。 PLCopen规则:CP22/CP24 重要性:低 例 22 . 例子 {attribute 'qualified_only'} {attribute 'strict'} TYPE SI
SA0010:只有一个组件的数组 检测只有一个元素的数组 理由:一个元素的数组可以被一个基本类型的变量替换。访问此变量比通过索引访问变量快得多。 例外:数组的长度通常由常量确定,并且是程序的参数。那么程序就可以处理不同长度的数组,并且如果长度仅为1则不必更改。这种情况应该相应地记录下来。 重要性:低 例 21 . 例子 PROGRAM PLC_PRG VAR aoiEmpty : ARRAY [2
SA0023:复杂的返回值 确定无法使用处理器的简单注册表副本返回的复杂返回值。这包括结构、数组和类型的返回值 STRING (不管已用内存的大小)。 理由:这是一个性能警告。如果函数、方法或属性的结果返回较大的值,则处理器在执行代码时会多次复制它们。这可能会导致运行时问题,应尽可能避免。可以通过传递结构化值来提高性能 VAR_IN_OUT 到一个函数或方法并将其填充到该函数或方法中。 重要性:中
SA0064:添加指针 检测指针的添加 理由:在 CODESYS ,指针运算一般是允许的,也可以适当使用。然而,它也代表了错误的来源。因此,存在通常禁止指针运算的编程规则。这个测试可以检查这样的需求。 重要性:中等 例 74 . 例子 PROGRAM PLC_PRG VAR iTest : INT; ariTest : ARRAY[0..10] OF INT; {attribute 'analys
SA0053:按位移位太大 在操作数按位移位(bit shift)的情况下,检测是否超出了操作数的数据类型宽度 理由:如果移位操作超出数据类型宽度,则为常数 0 生成。 如果旋转移位超过数据类型宽度,则难以读取。因此,应缩短旋转值。 重要性:高 例 62 . 例子 PROGRAM PLC_PRG VAR byTemp1 : BYTE; wTemp2 : WORD; dwTemp3 : DWORD;
SA0103:对非原子数据的并发访问 检测是否非原子变量(例如,具有数据类型 STRING , WSTRING , ARRAY , STRUCT 、FB 实例、64 位数据类型)用于多个任务 理由:在访问过程中没有同步的情况下,在一个任务中读,同时在另一个任务中写入时,可能会读到不一致的值。 重要性:中等 提示 对于某些数据类型,尤其是 64 位整数,访问是否是原子的取决于平台。仅当控制器不支持对
SA0105:多个实例调用 检测被多次调用的功能块的实例。为此,必须使用以下编译指示来标记功能块: {attribute 'analysis:report-multiple-instance-calls'} 理由: 某些功能块的设计方式是在一个循环中只能调用一次。此测试检查是否在多个位置进行呼叫。 重要性:低 PLCopen规则:CP16 / CP20 例 92 . 例子 // {attribut
SA0037: 对输入变量的写访问 检测输入变量( VAR_INPUT ) 可以通过 POU 内的写权限进行访问 理由:根据 IEC 61131-3 标准,输入变量不得在 POU 内更改。这种访问也是导致错误的原因,并使代码难以维护。这表明变量既用作输入变量又用作辅助变量。应该避免这种双重用途。 重要性:中等 例 46 . 例子 VAR_GLOBAL g_xGlob AT %QX0.0 : BOO
SA0117:数据类型为 BIT 的变量 检测数据类型的变量声明 BIT (可能在结构定义内) 理由:IEC 61131-3 标准不包含数据类型 BIT 。该代码更容易移植,无需 BIT 。 重要性:低 例 100 . 例子 TYPE Struct1 : STRUCT bitVar : BIT; iVar : INT; bVar : BOOL; END_STRUCT END_TYPE 输出在 留言
SA0021:传输临时变量的地址 检测临时变量(在堆栈上)到非临时变量的地址分配 理由:函数或方法的局部变量是在堆栈上创建的,它们仅在处理函数或方法时才存在。如果一个指针在处理完方法或函数后指向这种变量,那么你可以使用这个指针访问未定义的内存,或者访问另一个函数中不正确的变量。应不惜一切代价避免这种情况。 重要性:高 例 32 . 例子 FUNCTION TempVarInFUNC : DWORD