我想在没有对手的重复数据删除系统中使用MurmurHash3。例如,Murmurhash3会散列文件。
但是我在使用它时遇到了问题,这意味着我做错了什么。
Murmurhash3_x86_128()(source-code)函数接收四个参数。这是我对它们的理解:
键 - 输入数据到哈希
len - 数据长度
种子 - 种子
out - 计算哈希值
当运行它失败并出现分段错误时,由于代码的这一部分:
void MurmurHash3_x86_128 ( const void * key, const uint32_t len,
uint32_t seed, void * out )
{
const uint8_t * data = (const uint8_t*)key;
const uint32_t nblocks = len / 16;
...
const uint32_t * blocks = (const uint32_t *)(data + nblocks*16);
for(i = -nblocks; i; i++)
{
uint32_t k1 = blocks[i*4];
...
}
...
}
因此,如果我的数据长度大于15个字节(在这种情况下),则执行 for loop 。但是, blocks 指向我的数据数组的末尾,然后它开始访问该位置之后的内存位置。解释了分段错误。所以 key 不能仅仅是我的数据阵列。
我的问题是:我应该在键参数中添加什么内容?
解决了问题
在Mats Petersson的回答之后,我意识到我的代码有一个错误。我必须是一个int(签名),我没有签名。这就是它为块添加内存位置而不是减去的原因。
答案 0 :(得分:1)
blocks
指向正在计算的块中最后一个16字节的倍数。
i
从-nblocks开始,始终小于零(循环结束于零)。
因此,假设您有64个字节的数据,那么指针blocks
将指向data + 64
个字节,nblocks
将指向4
。
我们第一次到达k1 = blocks[i*4];
时i = -4
,所以得到索引-16
- 乘以sizeof(*blocks)
,即4(int = 4大多数架构中的字节数) - 所以我们得到-64
= data
的起始地址。