【问题标题】:A possible output from uninitialized pointer未初始化指针的可能输出
【发布时间】:2014-06-20 07:18:51
【问题描述】:

我有以下代码:

main(){
   char *buf;
   gets(buf);
   printf("Got %x\n",*(unsigned int *)buf);
}

我将 01234 放在标准输入上作为缓冲区。我以为总是会出现分段错误,但我的讲师说有时它可以打印“Got 33323130”作为输出。

谁能解释一下为什么?

【问题讨论】:

  • 读取未初始化的指针指向的位置会调用未定义的行为,即任何事情都可能发生。
  • 没有。没有人能真正解释为什么。这种行为、段错误和未初始化变量获得的实际值完全依赖于编译器。您可以查看生成的机器代码以获得更多见解

标签: c pointers casting segmentation-fault


【解决方案1】:

正如其他人所提到的,buf 是未定义的。由于它是在堆栈上声明的,因此其内容将取决于调用 main 之前堆栈上可能剩余的内容。通常,在调用 main 之前会发生很多事情(C 运行时初始化),因此尽管程序启动时堆栈最初为零(这是防止数据“泄漏”的操作系统安全要求),但很有可能调用 main 时为 buf 指针分配的堆栈区域将不再为零。它可以受环境变量、参数、编译选项等影响。

如果 buf 恰好指向一个可写的内存位置,那么程序将不会出现段错误,您将能够成功写入该位置。在这种情况下,您将在小端机器(例如基于 x86 的机器)上看到“Got 33323130”作为输出。在大端机器上,您会看到“Got 30313233”。

【讨论】:

    【解决方案2】:

    您所做的事情会引发“未定义的行为”,这意味着(ISO/IEC 9899:1999, 3.4.3):

    行为,在使用不可移植或错误的程序结构或 错误数据,本国际标准对此没有规定 要求

    注意可能的未定义行为范围从忽略 情况完全与不可预知的结果,要表现 在翻译或程序执行期间以有记录的方式 环境特征(无论是否发布 诊断消息),终止翻译或执行(与 发出诊断消息)。

    你的编译器和你的程序可以做任何事情。

    为什么它是未定义的行为?因为在 7.1.4(“库函数的使用”)中,C 标准要求:

    如果函数参数被描述为数组,则指针 实际传递给函数的值应使所有 地址计算和对对象的访问 [...] 在 事实有效。

    在 4 中(“一致性”):

    如果违反了“应”或“不应”要求 [...],则行为未定义。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-07-19
      • 2021-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多