C hash2无符号整数溢出
我目前正在尝试实现一个hashtable/trie,但当我将参数传递给hash2时,它会返回一个数字,但我得到了unsigned int overflow的运行时错误: test.c:53:12:运行时错误:无符号整数溢出:24930*1540483477不能在类型“unsigned int”中表示 test.c:60:4:运行时错误:无符号整数溢出:2950274797*1540483477不能在类型“unsigned int”中表示 6265 我在第53行和第60行放了一堆星星(*) 我不确定我是否传递了一些错误的参数。任何帮助都将不胜感激C hash2无符号整数溢出,c,murmurhash,C,Murmurhash,我目前正在尝试实现一个hashtable/trie,但当我将参数传递给hash2时,它会返回一个数字,但我得到了unsigned int overflow的运行时错误: test.c:53:12:运行时错误:无符号整数溢出:24930*1540483477不能在类型“unsigned int”中表示 test.c:60:4:运行时错误:无符号整数溢出:2950274797*1540483477不能在类型“unsigned int”中表示 6265 我在第53行和第60行放了一堆星星(*) 我不确
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed );
int main(void)
{
const char* s= "aa";
unsigned int number= MurmurHash2 (s, (int)strlen(s), 1) % 10000;
printf("%u\n", number);
}
unsigned int MurmurHash2 ( const void * key, int len, unsigned int seed )
{
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
const unsigned int m = 0x5bd1e995;
const int r = 24;
// Initialize the hash to a 'random' value
unsigned int h = seed ^ len;
// Mix 4 bytes at a time into the hash
const unsigned char * data = (const unsigned char *)key;
while(len >= 4)
{
unsigned int k = *(unsigned int *)data;
k *= m;
k ^= k >> r;
k *= m;
h *= m;
h ^= k;
data += 4;
len -= 4;
}
// Handle the last few bytes of the input array
switch(len)
{
case 3: h ^= data[2] << 16;
case 2: h ^= data[1] << 8;
case 1: h ^= data[0];
h *= m; ************************************************
};
// Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >> 13;
h *= m; **************************************
h ^= h >> 15;
return h;
}
#包括
#包括
#包括
无符号整数哈希2(常量void*键、整数len、无符号整数种子);
内部主(空)
{
const char*s=“aa”;
无符号整数=2(s,(int)strlen(s),1)%10000;
printf(“%u\n”,数字);
}
无符号整数哈希2(常量void*键、整数len、无符号整数种子)
{
//“m”和“r”是脱机生成的混合常量。
//它们不是真正的“魔法”,它们只是碰巧工作得很好。
常量无符号整数m=0x5bd1e995;
常数int r=24;
//将哈希初始化为“随机”值
无符号整数h=种子^len;
//在散列中一次混合4个字节
常量无符号字符*数据=(常量无符号字符*)键;
而(len>=4)
{
无符号整数k=*(无符号整数*)数据;
k*=m;
k^=k>>r;
k*=m;
h*=m;
h^=k;
数据+=4;
len-=4;
}
//处理输入数组的最后几个字节
开关(透镜)
{
案例3:h^=数据[2]13;
h*=m**************************************
h^=h>>15;
返回h;
}
unsigned int具有与系统相关的位数
在大多数系统上,这个数字是32位(4字节),但有些系统可能使用不同的大小(即在某些机器上是64位(8字节))
但是,杂音散列“字”是特定的大小。64位变量需要64位无符号类型,32位变量需要32位无符号类型
使用
中定义的uint64\u t
或uint32\u t
类型可以解决此不一致性
我想补充一点,后缀UL
(unsigned long)可能应该添加到您使用的任何数值常量中。即2950274797UL*1540483477UL
如@nwellnhof所示,您的代码似乎使用了算法的32位变体
乘法指令中的溢出在这些情况下是正常的(结果大于可用位数并被截断)。作为散列过程的一部分,这种数据丢失是可以接受的
考虑使用以下方法将预期结果告知编译器:
h = (uint32_t)(((uint64_t)h * m) & 0xFFFFFFFF)
祝你好运!
unsigned int
具有与系统相关的位数
在大多数系统上,这个数字是32位(4字节),但有些系统可能使用不同的大小(即在某些机器上是64位(8字节))
但是,杂音散列“字”是特定的大小。64位变量需要64位无符号类型,32位变量需要32位无符号类型
使用
中定义的uint64\u t
或uint32\u t
类型可以解决此不一致性
我想补充一点,后缀UL
(unsigned long)可能应该添加到您使用的任何数值常量中。即2950274797UL*1540483477UL
如@nwellnhof所示,您的代码似乎使用了算法的32位变体
乘法指令中的溢出在这些情况下是正常的(结果大于可用位数并被截断)。作为散列过程的一部分,这种数据丢失是可以接受的
考虑使用以下方法将预期结果告知编译器:
h = (uint32_t)(((uint64_t)h * m) & 0xFFFFFFFF)
祝您好运!您似乎正在使用UBSan选项
-fsanize=unsigned integer overflow
或启用此检查的其他选项,如-fsanize=integer
。说明:
请注意,与有符号整数溢出不同,无符号整数不是未定义的行为。然而,尽管它具有定义良好的语义,但它通常是无意的,因此UBSan提供了捕获它的方法
在杂音散列的情况下,乘法中的无符号整数溢出完全是故意的,因此应该禁用该选项
- 如果显式使用
,请将其删除-fsanize=unsigned integer overflow
- 如果由另一个选项启用,则传递
-fno sanitize=无符号整数溢出
- 或者,使用
\uuuu属性((无清除(“无符号整数溢出”))注释函数
2
<>另一个注释:您的代码似乎是从假定为32位<代码> int >代码> s中复制的。您应该考虑使用<代码> uint 32→t/代码>。 看起来,您正在使用UBSAN选项<代码> -FSANITIZE =无符号整数溢出< /代码>或其他选项如<代码> -FSATIZIZ=整数< /代码>来启用此检查。: 请注意,与有符号整数溢出不同,无符号整数不是未定义的行为。然而,尽管它具有定义良好的语义,但它通常是无意的,因此UBSan提供了捕获它的方法 在杂音散列的情况下,乘法中的无符号整数溢出完全是故意的,因此应该禁用该选项
- 如果显式使用
,请将其删除-fsanize=unsigned integer overflow
- 如果由另一个选项启用,则传递
-fno sanitize=无符号整数溢出
- 或者,使用
\uuuu属性((无清除(“无符号整数溢出”))注释函数
2
<>另一个注释:您的代码似乎是从假定为32位<代码> int >代码>的。您应该考虑使用<代码> UINT32×T 。