确定性仅在boost :: hash_combine中运行一个程序时才能保证

时间:2018-08-20 11:18:01

标签: c++ boost hash deterministic

在寻找整数的确定性哈希(多次运行,多台机器)时,我偶然发现了boost::hash_combine(size_t & seed, T const& v)。不幸的是,documentation中指出

  

此散列函数不适用于一般用途,并且不能保证在程序的单独运行期间是相等的-因此,请勿将其用于任何持久性存储或通信。

但是,在查看实现时,我没有看到任何可疑的代码可能在单独的运行中引起不同的行为-只是一些乘法和加法(可能有溢出),移位和异或运算,所有使用常量的东西。更重要的是,hasher多次执行时表现一致。

那么禁止在运行过程中确保确定性的实际问题在哪里?

在最有趣的部分下面粘贴:

template <class T>
inline void hash_combine(std::size_t& seed, T const& v)
{
    boost::hash<T> hasher;
    return boost::hash_detail::hash_combine_impl(seed, hasher(v));
}

template <typename T>
typename boost::hash_detail::basic_numbers<T>::type hash_value(T v)
{
    return static_cast<std::size_t>(v);
}

inline void hash_combine_impl(boost::uint64_t& h,
        boost::uint64_t k)
{
    const boost::uint64_t m = UINT64_C(0xc6a4a7935bd1e995);
    const int r = 47;

    k *= m;
    k ^= k >> r;
    k *= m;

    h ^= k;
    h *= m;

    // Completely arbitrary number, to prevent 0's
    // from hashing to 0.
    h += 0xe6546b64;
}

1 个答案:

答案 0 :(得分:1)

原因是哈希表中经常使用哈希。试图攻击服务的恶意用户(使用涉及哈希表的C ++代码)可能会通过对插入哈希表中的项强制执行哈希冲突来严重降低其性能(普通操作的性能从O(1)变为O(N)) )。通过让每个运行使用不同的哈希函数,这将变得更加困难。

std::hash也是这样标准化的。引用https://en.cppreference.com/w/cpp/utility/hash

  

仅要求散列函数在程序的一次执行中为相同的输入产生相同的结果;这允许使用盐腌的哈希来防止冲突DoS攻击。 (自C ++ 14起)