scanf导致seg错误?

时间:2014-03-05 07:46:26

标签: c scanf

gcc编译得非常好,但是一旦scanf接受了一个字符串就会出现故障。我有点不知所措。这是代码。

char *line[256];


void *mainThread()
{
        while (*line != "quit") {
                scanf("%s", *line);
                printf("%s", *line);
        }

        return;
}

有什么关于scanf我在这里不明白吗?

3 个答案:

答案 0 :(得分:5)

首先,您要为字符分配指针数组,而不是 char 数组:

char *line[256]; /* allocates 256 pointers to a character - 
                    (pointers are initialized to NULL) */

您需要分配一个字符数组:

char line[256]; /* allocates 256 characters */

其次,您需要使用strcmp来比较字符串 - 与!=,您正在比较line[0]中存储的指针(地址)(与{{1}相同使用指向字符串文字*line的指针,它们总是不同的。

您可以使用以下sscce作为起点:

"quit"

一些补充说明:

  • 有关分段错误的实际原因的说明,请参阅@Joachims答案。
  • 您声明函数返回#include <string.h> #include <stdio.h> char line[256]; int main() { while (strcmp(line, "quit") != 0) { scanf("%s", line); printf("%s", line); } return 0; } 指针,但您没有返回任何内容(使用void*没有参数)。然后,您应该将其声明为return
  • 不要使用void来读取输入,因为它可能会读取比分配的字符更多的字符,从而导致缓冲区溢出。请改用scanf()。另请参阅Disadvantages of scanf
  • 始终在启用所有警告的情况下进行编译,并认真对待 - 例如如果您使用的是gcc,请使用fgets()进行编译。

答案 1 :(得分:2)

声明全局变量时,它们被初始化为零。当你声明一个指向char的指针数组(而不是我认为你真正想要的char数组)时,你有一个256个NULL指针的数组。

在数组上使用解引用运算符*与执行例如array[0],这意味着作为scanfprintf的参数,您正在传递line[0],如上所述,它是NULL指针。取消引用NULL指针(如scanfprintf将会这样做)是未定义行为的情况,几乎总是会导致崩溃。

答案 2 :(得分:1)

它正在编译,因为您的程序在语法上是正确的。但是,它有严重的语义错误,由于段错误而显示为程序崩溃。全局数组line被初始化为零,作为任何全局变量。因为line是一个指针数组(不是一个预期的字符数组),所以零被解释为空指针NULL*lineline[0]相同,字符串文字"quit"计算为指向其第一个元素的指针。因此while条件与

相同
while(NULL != "quit") // always true

接下来,scanf("%s", *line);尝试将输入字符串写入line[0]指向的缓冲区,即NULL - 一个不等于任何内存位置地址的值。这将导致段错误并导致程序崩溃。

您的代码段中还有其他错误。让我们一个接一个。

char *line[256];

上述语句定义了一个256个指向字符的数组line,即其类型为char *[256]。你需要的是一个字符数组 -

char line[256];

您无法比较C中的数组。你可以做的是逐个元素地比较它们。对于字符串,您应该使用标准库函数strcmp。另请注意,格式字符串%s中的scanf转换说明符从stdin读取一个字符串,并将其写入下一个参数指向的缓冲区。它在结尾处放置一个终止空字节,但如果输入的字符串太大而无法保存缓冲区,则不会检查缓冲区溢出。这将导致未定义的行为,并且很可能由于非法内存访问而导致段错误。您应该通过在格式字符串中指定最大字段宽度来防止缓冲区溢出。

void *mainThread();

上面的函数声明意味着mainThread是一个返回void *类型指针的函数,并且取一个未指定但固定数量和类型的参数,因为空括号表示没有提供有关参数列表的信息。您应该在参数列表中编写void以表示该函数不带参数。另请注意,如果使用函数的返回值,函数中的空返回语句将导致未定义的行为,因为您没有返回任何内容,而是在函数的返回地址中使用垃圾值。假设您要返回字符串,则应将其定义为 -

char line[256];

char *mainThread(void) {
    while(strcmp(line, "quit") != 0) {
        scanf("%255s", line);    // -1 for the terminating null byte
        printf("%s", line);
    }
    return line;
}