std::string_view 编译时散列
Posted
技术标签:
【中文标题】std::string_view 编译时散列【英文标题】:std::string_view compile time hashing 【发布时间】:2016-06-09 08:37:07 【问题描述】:似乎 C++17 string_view 的 std::hash functions 不是 constexpr 的。
在我看来,绑定到 const char[] 的字符串视图可以在编译时进行散列处理(这会很不错),或者有什么可以防止这种情况发生?
【问题讨论】:
我认为hash<T>::operator()
中的任何一个都不是 constexpr,即使对于整数类型也是如此(或者至少我在 n4567 中找不到任何提及 constexpr 哈希的内容。)
啊我明白了,没注意到,不知道为什么。
【参考方案1】:
从 C++14 开始(参见 17.6.3.4 哈希要求,表 26),我们有:
返回的值应仅取决于持续时间的参数 k 的程序。 [注意:因此表达式 h(k) 的所有计算 相同的 k 值产生相同的结果对于给定的执行 程序。 -- 尾注]
两个different executions can give different hashes:
哈希函数只需要产生相同的结果 相同的输入在一个程序的单个执行中; 这允许 防止冲突 DoS 攻击的加盐哈希。
This behaviour is useful 缓解hash collision-based DoS attacks。
详情
以下是 C++17 标准中关于 Hash
概念要求的措辞:
返回的值应仅取决于参数 k 在项目期间。 [注:因此所有 表达式 h(k) 的评估具有相同的 k 的值产生相同的结果 程序的给定执行。 ——尾注]
它没有明确说明有关随机散列的任何内容。 std::hash
文本不强制也不排除随机散列。
历史
这是N3242 2011-02-28 的草案,其中没有提到“在计划期间”:
不应抛出异常。返回的值将取决于 关于论点 k。 [注意:因此表达式 h(k) 的所有计算 使用相同的 k 值产生相同的结果。 ——尾注
我们可以看到添加了“在程序期间”“对于程序的给定执行”作为“2291. std::hash
is vulnerable to collision DoS attack”的分辨率。
在实践中
AFAIU,std::hash
没有实现随机散列,但您可以编写自己的 my::secure_hash
。
【讨论】:
不幸的是,最后一句话根本不是真的。该标准确实要求该值仅取决于给定程序执行的参数,这是正确的。但是,这是因为某些实现只是将指针转换为哈希值。其他实现(例如 GCC)在运行时使用带有内置常量种子的 FNV1 可证明按字节进行散列,因此实际上不存在随机散列之类的东西。因此,该标准为我们提供了两个世界中最糟糕的一个:没有可预测的输出值,没有 constexpr,同时没有可靠不可预测的输出值。 @Damon:我想说这还不错。该标准为您提供的是使用不可预测的散列编写自己的my::secure_hash
和使用constexpr 能力编写自己的my::fast_hash
的能力。它使实现能够对std::hash
使用不可预测的散列。以上是关于std::string_view 编译时散列的主要内容,如果未能解决你的问题,请参考以下文章
Boost.Container flat_map 和 std::string_view
哈希<std::string> 与哈希<std::string_view>
除了 std::string_view 方法之外,std::string_view 比 char* 有啥优势吗?