C - 模size_t产生"The result of expression is undefined"



在64位系统上,当使用modulo运算符和size_t类型时,我从clang分析器得到以下警告:

htable.c:38:62: warning: The result of the ' ' expression is undefined [clang-analyzer-core.UndefinedBinaryOperatorResult]
return ht->num_buckets > 0 ? (ht->hash_fn(key, ht->seed) % ht->num_buckets)
^

完整跟踪

散列函数的结果具有size_t,并且桶的数量也是size_t。最终,这转化为无符号长。AFAIK结果不能为负数,我检查了bucket的数量是否为零。

哈希函数可能会溢出,但由于它用于链接哈希表,这不会导致问题(如果我没有错的话(。

这里怎么了?这是假阳性吗?

发生警告的功能:

static size_t
htable_bucket_idx(htable_t* ht, void* key)
{
if (!ht || !key) {
printf("htable - bucket_idx: Invalid Argument!n");
exit(-1);
}
return ht->num_buckets > 0 ? (ht->hash_fn(key, ht->seed) % ht->num_buckets)
: ht->hash_fn(key, ht->seed);
}

散列函数是FNV散列函数的粗略简化版本:

size_t
fnv_hash_ul(const void* in, unsigned int seed)
{
size_t             h     = seed;
const unsigned int prime = 0xFDCFB7;
unsigned long ul = *((unsigned long*) in);
return (h ^ ul) * prime;
}

htable_t的定义(为了简洁起见,省略了其他类型,根据要求添加(

typedef size_t (*htable_hash)(const void* in, unsigned int seed);
typedef struct htable
{
htable_hash      hash_fn;
htable_keq       keq;
htable_cbs_t     cbs;
htable_bucket_t* buckets;
size_t           num_buckets;
size_t           num_used;
unsigned int     seed;
} htable_t;

函数调用:

static int
htable_add_to_bucket(htable_t* ht, void* key, void* value, bool rehash)
{
if (!ht || !key) {
printf("htable - add_to_bucket: Invalid Argument!n");
exit(-1);
}
size_t idx = htable_bucket_idx(ht, key);
[...]

编译器信息:

clang version 11.1.0
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-pc-linux-gnu/10.2.0
Candidate multilib: .;@m64

GitHub上的htable.c
GitHub 上的htable.h

实际上,这似乎是一个假阳性。我能够通过将htable_rehash((从中更改来消除所有警告

static int htable_rehash(htable_t* ht)
{
...
ht->num_buckets <<= 1UL;
...
}

static int htable_rehash(htable_t* ht)
{
...
ht->num_buckets *= 2;
...
}

奇怪。

相关内容

最新更新