【问题标题】:Segfault when trying to use data from scanf?尝试使用scanf中的数据时出现段错误?
【发布时间】:2019-01-03 06:20:27
【问题描述】:

我对可能导致此问题的原因感到非常困惑,我真的很想了解幕后发生的事情。以下代码用于获取最大 99 个字符长度的字符串,将其放入名为 word 的变量中,然后读取长度;稍后我将通过字符串中的字符数量重新分配分配给它的内存,但现在我只想能够获得输入。这是代码段:

char* word = malloc(100);
printf("Enter a string:\n");
int x = scanf("%s", &word);
printf("Length = %d", x);
printf("Word is %s", word);

使用时会发生这种情况:

Enter a string:
123
1
Segmentation Fault

这里发生了什么?为什么这不起作用?我认为用 malloc 分配内存会给它足够的空间,然后 scanf 会将我的话放入变量中?我需要使用 malloc,因为我需要稍后重新分配,以免使用比以后需要更多的内存。

【问题讨论】:

  • int x = scanf("%s", &word); -> int x = scanf("%s", word);
  • @ChrisTurner 这是一个很好的链接,但你确定这是一个 dupe 吗?
  • @PaulR 我也有一个问题,为什么不需要写malloc(100*sizeof(char)),因为我们需要一个 100 字符长的字符串?
  • @Alan sizeof(char) 按照标准定义为1

标签: c segmentation-fault scanf


【解决方案1】:

看看你的sn-p:

char* word = malloc(100);
printf("Enter a string:\n");
int x = scanf("%s", &word);

问题出在我引用的最后一行。 scanf() 需要指向 %s 的某个 char 数组的指针。但是使用 address-of 运算符 (&) 获取 您的指针的地址,因此您将给 scanf() 一个指向您的指针 word 的指针.这是未定义的行为scanf() 只会覆盖指针 word(从而破坏它)——可能会发生其他奇怪的事情。简单的解决方法:删除&

这还不是上面代码的全部错误,下面这行:

int x = scanf("%s", word);

也有未定义的行为。这是因为你永远无法保证输入的前 99 个字符中会有空格,所以这段代码可能溢出你的缓冲区。始终使用字段宽度将scanf() 转换为字符串,如下所示:

int x = scanf("%99s", word);

最后,对于固定且相当少量的内存,实际上不需要动态分配它(而且我认为您不需要调用free())。只需将第一行替换为

char word[100];

您仍然可以以相同的方式编写其余代码。在大多数情况下,数组的标识符计算为指向第一个元素的指针,例如将其传递给函数时。

【讨论】:

    【解决方案2】:

    在您的代码中

     int x = scanf("%s", &word);
    

    应该改为

     int x = scanf("%99s", word); //99 chars to be scanned - at max - see note below
    

    因为word 已经是一个指向char 的指针,

    • %s 的预期参数类型
    • 指向你刚刚分配的内存。

    引用C11,第 §7.21.6.2 章,为fscanf() 家庭

    s

    [...] 如果不存在 l 长度修饰符,则相应的参数应为 指向足够大的字符数组的初始元素的指针,以接受 序列和一个终止的空字符,它将自动添加。 [....]

    注意:如有疑问/混淆,请务必检查数据类型。

    • word 属于 char * 类型 - 正确且预期的类型
    • &word 的类型为 char **。 - 类型不匹配

    也就是说,有几个提示

    • 始终检查库函数是否成功执行/返回。 (malloc()scanf() 等)在使用结果之前。
    • 始终对扫描进行大小限制,以防止缓冲区因输入过长而溢出。

    【讨论】:

    • 你能帮我理解为什么需要这样做吗?是由于字符串在 C 中的工作方式(作为字符数组)还是?这实际上是有道理的,所以如果我已经将变量定义为指针,我不需要在 scanf 函数中使用 & 吗?整洁!
    • @PixelRain 是的,我想你明白了,
    • @PixelRain 您可能应该阅读 C 教科书中处理指针的章节。
    【解决方案3】:

    问题出在:int x = scanf("%s", &word);。不要盲目使用&scanf。确实,您应该将地址传递给scanf,但在这里您传递的是word 的地址。变量word 本身就是一个地址(或者更确切地说,包含一个地址)。您希望从该地址开始写入数据。

    删除&。使用int x = scanf("%s", word);

    【讨论】:

      【解决方案4】:

      问题在于这个声明int x = scanf("%s", &word)。您已经声明了char* word = malloc(100),这意味着它是一个字符数组。您可以将语句修改为int x = scanf("%s", word)(不带&)。 查看https://www.tutorialspoint.com/c_standard_library/c_function_scanf.htm的示例代码

      传递word 本身为数组的第一个元素提供地址以存储读取的值。

      话虽如此,如果您需要的内存量在编译时已经知道,最好静态分配内存为:

      char word[100]

      要读取指定数量的字符,请使用表达式scanf("%<count>s", <stringVariable>。在您的情况下,它将是:

      scanf("%99s", word)

      此处提供示例代码:https://en.wikipedia.org/wiki/Scanf_format_string

      【讨论】:

        猜你喜欢
        • 2012-04-30
        • 2018-09-24
        • 1970-01-01
        • 2020-10-26
        • 2022-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多