【问题标题】:printf with newline character causing strange seg. fault带有换行符的 printf 导致奇怪的段。过错
【发布时间】:2014-07-29 05:24:11
【问题描述】:

我在执行这段代码 sn-p 时观察到一个奇怪的行为

#include <stdio.h>

void main()
{
    char *a[10] = {"hi", "hello", "how"};
    int i = 0, j = 0;
    for (i = 0;i < 10; i++)
            printf("%s\n", a[i]);
}

输出:

hi
hello
how
Segmentation fault

但是,如果我在 printf 语句中用空格字符替换 '\n' 字符,则没有 seg。故障来了

hi hello how (null) (null) (null) (null) (null) (null) (null) 

我在 Ubuntu 上使用 gcc v4.4.3。 换行符如何导致段。 printf 出错了?

【问题讨论】:

  • 我不明白这怎么能被描述为“奇怪”...
  • for (i = 0;i &lt; 3; i++) 怎么样,因为你有一个指向 3 数组的指针?

标签: c linux


【解决方案1】:

您拥有的是undefined behavior。您有一个包含十个指向char 的指针的数组,但只有前三个实际上指向有效的东西,而其余的指针是NULL 指针。取消引用 NULL 指针会导致未定义的行为,这有时会起作用,而其他时候它会使你的程序崩溃。

【讨论】:

  • 如果我错了,请纠正我,但 C 标准是否不要求 %s 与 NULL 仍被定义为行为?
  • @DrewMcGowen 刚刚检查确定,C11 规范没有说明任何内容。
【解决方案2】:

行为上的差异是由于gcc将printf("%s\n", ...)优化为puts(...),除了字符串为NULL的情况外,功能上是相同的。

在第二种情况下,gcc 无法优化调用,因此输出不同。

【讨论】:

    【解决方案3】:

    您有未定义的行为。您只初始化了 3 个指针,其余的都指向 NULL。当您尝试打印 NULL 指针时会导致未定义的行为。

    尝试以下方法,它会为您工作。

    void main()
    {
    char a[10][10] = {"hi", "hello", "how"}; // here statically i am allocating array. 
    // First three elements are initialized and the remaining elements contains null.
    int i = 0, j = 0;
    for (i = 0;i < 10; i++)
            printf("%s\n", a[i]);
    }
    

    【讨论】:

      【解决方案4】:

      只有数组中的前三个项目被初始化(通过三个字符串)。在尝试访问它们之前,您需要初始化其他七个 char * 指针。

      【讨论】:

        【解决方案5】:

        您只初始化了 10 个数组成员中的 3 个。访问未初始化指针的行为是未定义的。有时会崩溃,有时不会。

        【讨论】:

        • 当数组或结构从大括号括起来的初始化程序中初始化时,任何没有初始化程序的成员都会被初始化,就像给定了0一样。所以其他指针被初始化为空指针。
        • @kristianp uninitialized not 等同于 NULL。事实上,MSVC 在调试中经常将未初始化的值“初始化”为 0xCCCCCCCC。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-10
        • 1970-01-01
        • 1970-01-01
        • 2015-09-03
        • 1970-01-01
        相关资源
        最近更新 更多