【问题标题】:How does an uninitialized variable get a random value? [duplicate]未初始化的变量如何获得随机值?
【发布时间】:2013-06-20 14:43:00
【问题描述】:

假设我声明了一个变量x 并让它保持未初始化状态。我继续打印它的值。我看到了一些垃圾。

它来自哪里?另外为什么不使用它来生成随机数?我的意思是不要使用伪随机生成器。

【问题讨论】:

标签: c undefined-behavior initialization


【解决方案1】:

“随机”值就是内存中那个位置的剩余值。内存在被释放时通常不会被擦除/归零,所以那里的任何东西都会一直存在直到它被覆盖。

【讨论】:

【解决方案2】:

垃圾可能来自两个地方:

  • 当动态 RAM 上电时,单元保持在任意状态直到初始化;这是大多数内存硬件实现的属性
  • 当您的程序运行时,它会留下以前使用过但不再在范围内的变量值。此属性可用于攻击:分析程序遗留的垃圾可能会将信息提供给不道德的插件编写者或您使用的其他库。

【讨论】:

    【解决方案3】:

    未初始化变量的值是在分配给该变量之前存在于相应内存区域的值。大多数情况下,它是不可预测的,并且取决于此内存区域内之前发生的任何事情。

    这实际上有时用作额外的熵来生成伪随机数。多年前,一位 Debian 开发人员认为未初始化的变量是 OpenSSL 中的一个错误,并将其设置为零。然后生成的密钥变得有些猜测,现在每个 Debian 用户都必须在他们的机器上安装一长串黑名单。

    【讨论】:

      【解决方案4】:

      简短的回答?这取决于您的编译器 - 但不要这样做。

      长答案:
      访问未初始化的 POD(普通旧数据,例如 int)类型的值会调用 未定义的行为,这意味着 C 标准在这种情况下对符合要求的实现没有任何要求。因此,允许编译器发出启动 nethack、格式化硬盘驱动器或什么都不做的机器代码,同时仍符合 C 标准——只要它可以证明未定义的行为发生在程序中的任何位置。

      (另请阅读:What Every C Programmer Should Know About Undefined Behavior

      那么,实际上(可能)会发生什么?
      在大多数现代编译器没有启用优化上,编译器将简单地将堆栈(或寄存器)上的一个槽分配给变量,然后在被询问之前访问该位置的任何内容。结果似乎是“随机记忆”,但实际上是it's not very random at all

      如果我启用优化会发生什么?
      如果您随后在更高的优化级别上编译您的代码(或者编译器已更新并且现在更积极地优化),那么所有的赌注都没有了。例如,编译器可能会删除任何涉及x 的调用,将x 分配到与其他变量相同的位置(认为不可能使用x,因为它尚未初始化),或者@987654323 @。

      换句话说,当您访问那个未初始化的变量时,您的程序就可以开始在您的控制之外执行任何事情。不要这样做 - 这里是龙。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-03
        • 1970-01-01
        • 1970-01-01
        • 2021-05-09
        • 1970-01-01
        • 1970-01-01
        • 2016-07-31
        • 1970-01-01
        相关资源
        最近更新 更多