从版本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
并将此视为错误,而不是可移植性问题。
它是C代码(包含在C ++主导的项目中),使用C ++ 98兼容编译器编译,同时按预期运行数十年。 Cppcheck使用C ++ 03,C89,自动检测语言运行。
我承认代码应该更好地重写。 但在此之前,我试图弄清楚:它真的依赖于评估顺序吗? 根据我的理解,正在首先评估正确的操作数(它需要在调用之前),然后使用最后完成的ipos
的增量进行赋值(到msg[ipos]
)。
我错了这个假设,还是只是假阳性?
此代码确实依赖于评估顺序,其方式未明确定义:
msg[ipos++] = checksum(&msg[1], ipos-1);
具体来说,没有指定ipos++
是否会在评估ipos-1
之前或之后递增。 这是因为=
处没有“ 序列点 ”,只在完整表达式的末尾( ;
)。
函数调用是一个序列点。 但这只能保证ipos-1
在函数调用之前发生。 它不能保证ipos++
之后发生。
似乎应该以这种方式重写代码:
msg[ipos] = checksum(&msg[1], ipos-1); ipos++; // or ++ipos
=
的操作数的评估顺序未指定。 首先,代码依赖于未指定的行为。
更糟糕的是, ipos
在同一个表达式中使用了两次,其间没有序列点,因为不相关的目的 – 导致未定义的行为。
C99 6.5
在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的计算修改一次。 此外,先前的值应该是只读的,以确定要存储的值。
同一文本适用于C90,C99,C ++ 98和C ++ 03。 在C11和C ++ 11中,措辞已经改变,但含义是相同的。 这是未定义的行为,前C ++ 11。
编译器不需要对未定义的行为进行诊断。 你很幸运。 这不是误报 – 您的代码包含一个严重的错误,从原始C代码开始。
以上就是c/c++开发分享确定“未知的评估顺序”相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/546006.html