使用fgets将数据读入未初始化的char指针变量时,在第二次读取时崩溃

时间:2019-04-30 15:13:24

标签: c pointers undefined-behavior fgets

我知道我们无法使用fgets将数据读取到未初始化的char指针中。关于堆栈溢出的这一点,有很多问题。所有答案都表明您无法将数据加载到未初始化的指针变量中。

第一个代码片段中所示的程序能够使用fgets填充第一个未初始化的char指针(* str2),但是在尝试将数据读取到第二个未初始化的char指针(* str3)时崩溃。

我可以使用传统方法使其工作,例如在填充之前预先为指针分配内存(如下面的第二个代码片段所示)。我的问题是为什么它对第一个变量有效但对第二个变量无效?

问题代码

#include <stdio.h>

int main()
{
    char str1[100], *str2, *str3;
    // Prints fine

    printf("First String: ");
    fgets(str1, 20, stdin);
    printf("%s", str1);

    // Prints fine      
    printf("Second String: ");
    fgets(str2, 20, stdin);
    printf("%s", str2);

    // Program crashes on this input
    printf("Third String: ");
    fgets(str3, 20, stdin);
    printf("%s", str3);

    return 0;

}

工作代码

#include <stdio.h>

int main()
{
    char str1[100], str2[20], str3[20];
    printf("First String: ");
    fgets(str1, 20, stdin);
    printf("%s", str1);

    printf("Second String: ");
    fgets(str2, 20, stdin);
    printf("%s", str2);

    printf("Third String: ");
    fgets(str3, 20, stdin);
    printf("%s", str3);

    return 0;

}

2 个答案:

答案 0 :(得分:5)

以您的情况

// Prints fine      
printf("Second String: ");
fgets(str2, 20, stdin);
printf("%s", str2);

包含对未初始化指针的写入,该指针包含不确定的值,这意味着它将调用undefined behavior

一旦程序具有UB,就无法保证。拥有UB的副作用之一是表现为“正常(正常)工作”,也不保证“崩溃”或分段错误。就是这样,未定义。

故事的寓意:不要试图用从包含未定义行为的程序获得的输出来推理。

答案 1 :(得分:1)

仅因为您使用的是未初始化的指针,并不保证程序会崩溃。未定义的行为通常会导致不可预测性。在您的特殊情况下,即使未初始化,在计算机上以及在编译器上,指针也恰好指向有效内存,但这可能会因编译器和编译器而异。