0
  • 平台:x86 Linux 3.2.0 (Debian 7.1)
  • 编译器:GCC 4.7.2 (Debian 4.7.2-5)

我正在编写一个函数,该函数通过读取分配的内存部分以获取“随机”值来生成“随机”整数。这个想法是基于未初始化变量具有未定义值的事实。我最初的想法是使用 malloc() 分配一个数组,然后使用其未初始化的元素生成一个随机数。但是 malloc() 往往会返回 NULL 内存块,所以我不能保证有任何东西可以读取。所以我考虑读取一个单独的进程内存,以便几乎保证 NULL 以外的值。我目前的想法是以某种方式找到第一个有效的内存地址并从那里读取,但我不知道该怎么做。我尝试初始化一个指向 NULL 的指针,然后将其递增 1,但是如果我尝试打印引用的内存位置,则会发生分段错误。所以我的问题是如何读取单独的进程内存。除了读取它之外,我不需要对内存做任何事情。

4

5 回答 5

5

这个想法是基于未初始化变量具有未定义值的事实。

不,你不能。它们具有垃圾值,这意味着该内存中发生的任何事情都不是随机的。

于 2013-08-20T00:57:39.147 回答
3

您无法读取单独的进程内存,内核会保护您免于这样做,因为它通常是由于设置指针时出错而发生的。即使它们是可能的,你也不会得到任何接近随机整数的东西。为什么不读/dev/random呢?

于 2013-08-20T01:02:50.403 回答
3

通过软件在计算机中生成随机数是困难的(有硬件随机数生成器)。新程序中的内存是一个可怕的来源,尤其是在早期,因为操作系统在启动程序之前已将所有内存归零。您看到的任何非零值都是初始化代码遗留下来的。

假设您想要“自己动手”数字,则时间的微/纳秒数字是一种老式的解决方案……理论如下所示……玩自己的数字。具有大素数的模会很好。只要确保丢弃超过 1/1,000 秒的任何东西。

   (长长)(纳米 * 1E10 ) % 1000

这假设您是通过手动命令而不是计划作业开始的。

如果您在 UNIX 上运行,请查看从 /dev/urandom 中读取几个字节,或者小心谨慎地从 /dev/random(阅读手册页)中读取。

Windows 有它自己的 API。在 perl 中,

   新的 Win32::API "advapi$b32","CryptAcquireContextA",'PNNNN','N' ||
                     死 "$^E\n"; # 使用 MS 加密或死亡

良好的随机数生成器为获得良好的数字所做的认真工作超出了快速响应的范围;这通常依赖于硬件,例如时间戳中断。

于 2013-08-20T01:20:33.550 回答
3

随机数具有某些特殊性质。计算机内存一般不满足这些属性。

如果我对计算机内存进行采样,大量的数据会非常相似,并且某些数字存在的概率很低,甚至可能在计算机的整个内存中都找不到。

更不用说,如果我读取了分配给程序的内存之外的一些内存,操作系统会用 SEGFAULT 杀死我。

这是一个坏主意,在很多层面上。使用适当的随机数生成器。

于 2013-08-20T06:29:03.697 回答
2

这个想法是基于未初始化变量具有未定义值的事实。

就您无法预测它们包含的内容而言,它们是未定义的。它们真正包含的内容主要取决于操作系统。

回到过去的 DOS 时代,您可能会依赖这样一个事实,即如果您在当前会话中执行多个程序,内存中就会出现垃圾。但即便如此,这些数据也不是随机性的可靠来源。

如今,情况有所不同。

  • 如果您在堆栈上有变量,并且在当前程序运行中您从未像现在这样深入堆栈,则您的局部变量为 0。否则,它们包含来自先前函数调用的数据。

  • 如果您malloc()和 libc 从已使用的内存池中获取返回的内存,它也可能包含垃圾。但是,如果它是从操作系统新获取的,则将其归零。

我最初的想法是使用 malloc() 分配一个数组,然后使用其未初始化的元素生成一个随机数。但是 malloc() 往往会返回 NULL 内存块,所以我不能保证有任何东西可以读取。

(不是 NULL,而是 0 或 NUL。)请参阅我的最后一点:这取决于malloc()ed 区域的历史。

所以我考虑读取一个单独的进程内存,以便几乎保证 NULL 以外的值。

你不能,因为进程是相互分离和屏蔽的。

正如其他人所说,有更好的随机性来源。/dev/random如果你肯定需要真正的熵,/dev/urandom否则。

于 2013-08-20T07:01:11.447 回答