【问题标题】:Finding Allocated Memory查找分配的内存
【发布时间】:2013-08-20 00:53:09
【问题描述】:
  • 平台:x86 Linux 3.2.0 (Debian 7.1)
  • 编译器:GCC 4.7.2 (Debian 4.7.2-5)

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

【问题讨论】:

  • 什么是“空内存块”?一个初始化为所有字节为零的?还是别的什么?
  • 另外,如果你的进程读取他们进程的内存,人们会感到不安;您可能正在读取密码、信用卡号、社会保险号或操作系统应该对进程保密的各种其他内容。您必须是 root 才能读取任意其他用户的进程;如果你真的想要,你可以读取你自己进程的内存,但你真的不这样做,因为你不是在处理真正的随机值。
  • /dev/[u]random 随机得多,问题也少得多。
  • 读取未初始化的内存(作为对变量的概括)会引发未定义的行为。不要不要这样做!

标签: c linux memory


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

      【解决方案3】:

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

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

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

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

      【讨论】:

        【解决方案4】:

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

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

         (long long)(nano * 1E10 ) % 1000

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

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

        Windows 有自己的 API。在 perl 中,

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

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

        【讨论】:

          【解决方案5】:

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

          它们是未定义的,因为你无法预测它们包含什么。它们真正包含的内容主要取决于操作系统。

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

          如今,情况不同了。

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

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

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

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

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

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

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

          【讨论】:

            猜你喜欢
            • 2017-11-14
            • 2012-11-22
            • 1970-01-01
            • 2011-12-20
            • 1970-01-01
            • 2012-05-14
            • 1970-01-01
            • 2017-04-07
            • 2010-11-06
            相关资源
            最近更新 更多