Wol*_*olf 21 c c++ static-analysis operator-precedence cppcheck
从版本1.80开始,Cppcheck告诉我
表达式'msg [ipos ++] =校验和(&msg [1],ipos-1)'取决于副作用的评估顺序
在这个代码序列中(简化,data是一个变量)
BYTE msg[MAX_MSG_SIZE]; // msg can be smaller, depending on data encoded
int ipos = 0;
msg[ipos++] = MSG_START;
ipos += encode(&msg[ipos], data);
msg[ipos++] = checksum(&msg[1], ipos-1); // <---- Undefined Behaviour?
msg[ipos++] = MSG_END; // increment ipos to the actual size of msg
Run Code Online (Sandbox Code Playgroud)
并将此视为错误,而不是可移植性问题.
它是C代码(包含在C++主导的项目中),使用C++ 98兼容编译器编译,同时按预期运行数十年.Cppcheck使用C++ 03,C89,自动检测语言运行.
我承认代码应该更好地重写.但在此之前,我试图弄清楚:它真的依赖于评估顺序吗?根据我的理解,正在首先评估正确的操作数(它需要在调用之前),然后msg[ipos]使用ipos最后完成的增量进行赋值(to ).
我错了这个假设,还是只是假阳性?
Joh*_*nck 41
此代码确实依赖于评估顺序,其方式未明确定义:
msg[ipos++] = checksum(&msg[1], ipos-1);
Run Code Online (Sandbox Code Playgroud)
具体而言,未指定是否ipos++在ipos-1评估之前或之后递增.这是因为在完整表达式(the )的末尾没有" 序列点 " .=;
函数调用是一个序列点.但这只能保证ipos-1在函数调用之前发生.它不能保证ipos++在之后发生.
似乎应该以这种方式重写代码:
msg[ipos] = checksum(&msg[1], ipos-1);
ipos++; // or ++ipos
Run Code Online (Sandbox Code Playgroud)
该评价的顺序的操作数=是不确定的.首先,代码依赖于未指定的行为.
更糟糕的是,ipos在同一个表达式中使用了两次,其间没有序列点,出于不相关的目的 - 这会导致未定义的行为.
C99 6.5
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算来修改一次.此外,先前的值应该只读以确定要存储的值.
同一文本适用于C90,C99,C++ 98和C++ 03.在C11和C++ 11中,措辞已经改变,但含义是相同的.这是未定义的行为,前C++ 11.
编译器不需要对未定义的行为进行诊断.你很幸运.这不是误报 - 您的代码包含一个严重的错误,一直到原始的C代码.
| 归档时间: |
|
| 查看次数: |
1411 次 |
| 最近记录: |