Klocwork抱怨unsigned to zero的比较总是正确的——为什么?

Klocwork complains about unsigned to zero comparison that is always true -- WHY?

本文关键字:为什么 比较 unsigned 抱怨 to zero Klocwork      更新时间:2023-10-16

Klocwork说" unsigned值与0的比较总是为真",在以下条件行:

#define MAX_VALUE 8589934592 //2^33
...
uint64_t val = get_val();
if (val >= MAX_VALUE)
{
  return ERROR_INVALID_VALUE;
}

为什么?MAX_VALUE不为0…

请建议。

提前感谢。

#define MAX_VALUE 8589934592 //2^33

这个文字可能是一个问题,这取决于你使用的是哪个版本的c++,以及你的编译器选择如何处理它。

在2003年标准中,如果一个无后缀的十进制字面值在int范围内,则它的类型是int;如果它在long int范围内,则它的类型是long int;否则,行为是未定义的。如果您的gcc版本符合2003标准,则行为的不确定性可能表现为8589934592求值为0,这可以解释您所看到的问题。(但我希望有关于整数字面值超出范围的警告;你收到这样的警告了吗?

在2011标准中,这样的字面值可以是intlonglong long类型。(c++ 2003没有long long;它是从C99借来的

(注意^是位异或操作符;c++没有求幂运算符。这在注释中并不重要,但2**33可能更清楚,尽管这也不是一个有效的c++表达式。

...
uint64_t val = get_val();

get_val()返回什么类型?这应该不会影响警告,但知道这一点会很有趣。

if (val >= MAX_VALUE)

如果long在您的系统上是64位,那么这应该是可以的。如果long是32位,那么uint64_t必须比long/unsigned long更宽——这意味着你的编译器不符合c++ 2003模式。

下列程序的输出是什么?

#include <stdint.h>
#include <limits.h>
#include <iostream>
#include <ctime>
uint64_t get_val();
const char *type_name(int i) { return "int"; }
const char *type_name(long i) { return "long"; }
const char *type_name(unsigned long i) { return "unsigned long"; }
const char *type_name(long long i) { return "long long"; }
const char *type_name(unsigned long long i) { return "unsigned long long"; }
int main() {
    std::cout << "UINT_MAX   = " << UINT_MAX << "n";
    std::cout << "ULONG_MAX  = " << ULONG_MAX << "n";
    std::cout << "8589934592 = " << 8589934592 << "n";
    std::cout << "8589934592 is of type " << type_name(8589934592) << "n";
    uint64_t val = time(0);
    if (val >= 8589934592) {
        std::cout << "It's getting late!n";
    }
}

对于比较,Klocwork给出了什么警告?如果Klockwork给您一个与程序输出不一致的警告,这可能是Klocwork中的一个bug(您应该报告)——或者您可能只需要用不同的选项调用它。(我自己从来没用过Klocwork)

您可以通过使用-std=c++0x调用g++来解决(或至少绕过)这个问题。

像Klocwork这样的工具有一定的"误报"率,通常是15%,但在某些情况下高达50%,实际上我的工作的很大一部分是看静态代码分析工具的输出,并决定他们报告的错误是否为假阳性(或是否有假阴性)

长话短说,向我们展示get_val()的原型,并告诉我它应该返回什么类型,我将了解它为什么报告该消息以及它是否为FP。

不使用大数字的替代方案(避免文字大小问题)

const int MAX_VALUE_LOG2 = 33;
...
uint64_t val = get_val();
if ( (val >> MAX_MAX_VALUE_LOG2) > 0)
{
  return ERROR_INVALID_VALUE;
}