散列字符串值导致Linux与Windows中C ++的输出不同

问题描述 投票:3回答:1

我正在尝试对单个std::stringstd::vector<std::string>值进行哈希处理。我正在关注cppreferenceboost中的示例。当代码被编译并在Windows vs Linux上运行时,我得到不同的结果。

MyHasher.h的头文件如下。

class MyHasher {
 private:
  MyHasher() = delete;
 public:
  static std::size_t hash(std::vector<std::string> ids);
  static std::size_t hash(std::string s);
  static void hashCombine(std::size_t &seed, std::size_t value);
};

CPP文件MyHasher.cpp如下。

std::size_t MyHasher::hash(std::vector<std::string> ids) {
  std::size_t seed = 0;
  for (auto id : ids) {
    std::size_t h = std::hash<std::string>{}(id);
    hashCombine(seed, h);
  }
  return seed;
}
std::size_t MyHasher::hash(std::string s) {
  std::size_t seed = 0;
  std::size_t h = std::hash<std::string>{}(s);
  hashCombine(seed, h);
  return seed;
}
void MyHasher::hashCombine(std::size_t &seed, std::size_t value) {
  seed ^= value + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

然后一个示例程序如下运行。

int main() {
  std::cout << std::to_string(MyHasher::hash("0")) << " | 0" << std::endl;
  std::cout << std::to_string(MyHasher::hash(std::vector<std::string>{"0"})) << " | 0" << std::endl;
  std::cout << std::to_string(MyHasher::hash(std::vector<std::string>{"0", "1"})) << " | 0 1" << std::endl;
  return 0;
}

在Linux(g ++ 7.4.0)上,输出如下。

2297668036269395695 | 02297668036269395695 | 010545066640295778616 | 0 1

在Windows(Visual Studio Community 2019,MSVC-14.0)上,输出如下。

12638135526163551848 | 012638135526163551848 | 01964774108746342951 | 0 1

关于这种差异有什么想法吗?

我真正想要的是始终产生唯一的哈希输出的方法,该输出取决于输入,但是跨平台且固定宽度。宽度可以说并不重要,但只要与输入相同,宽度相同即可。

c++ boost hash hashcode
1个回答
3
投票

在文档中。在std::hash中明确提到:

实际的散列函数取决于实现

仅要求散列函数在程序的一次执行中为相同的输入产生相同的结果;

我对哈希函数不确定,该函数总是为相同的输入返回相同的哈希。我在Google上搜索了一下,但没有找到我敢提出的内容。

假设MS VC ++和g ++的std库可能是不同的实现,则不能期望它为相同的输入产生相同的哈希。

[仔细阅读引用的第二部分,您甚至不能指望同一程序在不同的过程中(例如,启动,退出和再次启动时)对相同的输入产生相同的散列。


Cryptographic hash functions可能是一个解决方案,但授予的属性是:

  • 这是确定性的,意味着相同的消息始终导致相同的哈希]
  • 快速计算任何给定消息的哈希值
  • 无法生成产生给定哈希值的消息
  • 无法找到具有相同哈希值的两条不同消息对消息进行很小的更改就应该广泛地更改哈希值,以使新的哈希值看起来与旧的哈希值不相关(avalanche effect

Checksums与哈希函数有关。对于校验和,必须要求对于相同的输入产生相同的输出(可靠)。

因此,基于哈希函数的校验和实现也应符合OP的要求。

SSE: Which hashing algorithm shoud I use for a safe file checksum?的可接受答案建议SHA256 or SHA512

[这让我想起了,我最近听到了git uses a variation of SHA-1,但我也听到了git may use SHA256 as well,这在我看来与OP可能具有的用例类似。

© www.soinside.com 2019 - 2024. All rights reserved.