是堆栈指针,是伪随机数的良好来源

is a stack pointer a good source of pseudo-random numbers

本文关键字:随机数 堆栈 栈指针      更新时间:2023-10-16

例如:

int main()
{
  int p;
  ::std::cout << ::std::uintptr_t(&p) << ::std::endl;
}

如果重复执行,这将始终产生"随机"数字。类似的事情可以在C中完成。我看不到任何关于它的UB。

我非常依赖于您对随机数分布设置的要求。序列1,1,1,1,1,11,1,1,1是随机的吗?事实上很难说,但如果你对正态分布进行测试,它肯定会失败。伪随机数生成器是专门为匹配您想要从中获得的随机分布的属性而设计的。

如果你耍了一些花招来得到一个以前未知的数字(我故意不称之为随机),这个数字对你来说可能是随机的,但很可能有一些模式你根本没有发现。

TL;DR:要写出一个好的rng并不容易。如果您需要随机数字,请使用可用的数字。

如果操作系统将程序的堆栈地址随机化,则可以从本地变量的地址中提取几个随机位。这些可能是高质量的随机位(如果你的操作系统很好的话),但只有少数,因为:

  • 对对齐有严格的要求(因此低位是恒定的,而不是随机的)
  • 任何操作系统都可能出于方便的原因限制用户程序的地址空间(因此高位将是恒定的)

因此,这种方法并不好,因为它的结果严重依赖于操作系统(作为一个极端的例子,用户可以禁用ASLR,而您的随机数生成器将停止为该用户工作)。

,无

您不能使用变量地址、未初始化变量的值等作为随机数的来源。

其中一些使用会让你直接进入"未定义行为领域",在那里你的编译器可以对你的代码做可怕的事情。

有些只是并不是真的那么随机。

如果您想要随机数,请使用<random>,并且如果您不直接使用random_device(对于非加密安全数字,您可能不希望这样做),请确保您正确地为生成器播种。

甚至不要考虑rand()——忘记它的存在。太可怕了。

您应该使用std::seed_seq来混合多个熵源,然后使用它来为生成器种子。假设还包括其他更高质量的源(尤其是std::random_device),则将变量的地址作为seed_seq的许多输入之一是可以的。

  • 作为随机数本身的来源,这非常糟糕,因为对于一个严重的对手来说,这是非常可预测的。正如其他人所说,地址空间是有限的,满足int对齐要求的地址要少得多,除此之外,将程序加载到内存中的算法(如果没有文档记录)至少不是为太多随机性而构建的
  • 作为的来源,它取决于操作系统。如果操作系统不随机化,就会损害可读性——因为读代码的人可能会错误地认为你在添加熵。如果操作系统真的随机化了,它仍然不会是一个很好的熵源,你必须将它与其他更好的源结合起来进行补偿——这些源必须完全独立于随机地址的熵源

在任何情况下,这都是假设您使用变量的地址(完全有效),而不是其。如果调用未定义的行为,操作可能会丢弃所有的熵。