如何解决取模 size_t 产生“表达式‘’的结果未定义”
在 64 位系统上,当使用模运算符和 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,bucket的个数也是size_t。最终这会转化为 unsigned long。 AFAIK 结果不能为负,我检查了桶数是否为零。
散列函数可能会溢出,但由于它用于链式散列表,因此不会导致问题(如果我没记错的话)。
这里有什么问题? 这是误报吗?
发生警告的函数:
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
htable.c on GitHub
htable.h on GitHub
解决方法
实际上,这似乎是误报。我能够通过更改 htable_rehash() 来消除所有警告:
static int htable_rehash(htable_t* ht)
{
...
ht->num_buckets <<= 1UL;
...
}
到
static int htable_rehash(htable_t* ht)
{
...
ht->num_buckets *= 2;
...
}
奇怪。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。