C++ | 如何安全地初始化 std::mt19937
           C++ | 如何安全地初始化 std::mt19937  背景  在看到 C++ Seeding Surprises  ᴮᵃᶜᵏᵘᵖ  这篇文章之前,我一直使用如下代码初始化 std::mt19937 :  std::mt19937 mtr(std::random_device{}());  问题  std::random_device  可能根本不是随机的  旧版 MinGW 中的 GCC 将其实现为确定性的,参见 std::random_device  not working properly  ᴮᵃᶜᵏᵘᵖ ,这一问题已在 MinGW GCC 9.2  中修复。  std::random_device  的值域不够大  std::random_device  的值域同 unsigned int ,在我的环境中为 [0,2^{32}-1] ,提供了 32 位的随机性。  然而, 2^{32}  并不是一个很大的数字。我们进行了一组 测试  ᴮᵃᶜᵏᵘᵖ ,在 1.75  秒内遍历了 10^6  个数据,因此预计可以在 2.09  小时内遍历完 2^{32}  种情况。  众所周知,只要知道种子,就可以预测整个随机序列。因此,对于需要高安全性的用例来说,32 位的种子远远不够。   需要高安全性的用例应当使用 密码学安全伪随机数生成器  ᴮᵃᶜᵏᵘᵖ 。   std::seed_seq  的实现不靠谱  上面的代码中,我们只给 std::mt19937  提供了一个 32 位整数,但是 Mersenne Twister 的状态包含 624 个 32 位整数(参见 维基百科  ᴮᵃᶜᵏᵘᵖ ),因此标准库会使用 std::seed_seq  来扩充状态。  然而 std::seed_seq  的实现有问题。  在使用 32 位整数进行播种时,包括 7  和 13  在内的大约 \frac{2^{32}}e  个数永远不可能作为 std::mt19937  生成的第一个数。如果你运行如下代码,函数 send_detailed_tracking_info_secretly  永远不会被调用。  std::mt19937 mtr(std::random_device{}()); if (mtr() == 7) /* lucky seven! you ...