2014-03-05 216 views
0

海湾合作委员会编译得很好,但只要scanf接受一个字符串它seg错误。我有点不知所措。这是代码。scanf导致seg故障?

char *line[256]; 


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

     return; 
} 

有一些关于scanf函数我不理解这里?

+0

你有没有分配任何内存'line [0] = malloc(...)'? –

回答

0

它正在编译,因为你的程序在语法上是正确的。然而,它具有严重的语义错误,由于段错误而导致程序崩溃。作为全局变量,全局数组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。另请注意,格式字符串scanf中的%s转换说明符从stdin中读取一个字符串,并将其写入下一个参数指向的缓冲区。它在结尾处放置一个终止空字节,但如果输入的字符串太大而不能容纳缓冲区,则它不会检查缓冲区溢出。这会导致未定义的行为,并且由于非法内存访问,很可能导致段错误。您应该通过在格式字符串中指定最大字段宽度来防止缓冲区溢出。

void *mainThread(); 

上述函数声明意味着mainThread是功能返回void *类型的指针,并采取的参数未指定但固定数量和类型,因为空括号意味着没有关于参数列表信息被提供。您应该在参数列表中写入void以表示该函数不带任何参数。还要注意,如果使用函数的返回值,则函数中的空return语句会导致未定义的行为,因为您没有返回任何内容,而是在函数的返回地址中使用垃圾值。假设你想返回字符串,它应该被定义为 -

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; 
} 
4

首先,你分配的指针数组字符,而不是一个字符的数组:

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

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

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

其次,您需要使用strcmp来比较字符串 - 与!=,您正在比较存储在中的指针(地址)(与*line相同),并带有一个指向字符串字面值"quit"的指针,它们总是不同的。

您可以使用以下sscce为出发点:

#include <string.h> 
#include <stdio.h> 

char line[256]; 

int main() 
{ 
    while (strcmp(line, "quit") != 0) { 
     scanf("%s", line); 
     printf("%s", line); 
    } 

    return 0; 
} 

一些其他注意事项:

  • 见@Joachims答案分割故障的实际原因的解释。
  • 你声明你的函数返回一个指针void*,但你不返回任何东西(使用return不带参数)。您应该简单地将其声明为void
  • 不要使用scanf()读取输入,因为比你分配导致缓冲区溢出,可能更多的字符。改为使用fgets()。另见Disadvantages of scanf
  • 始终在启用所有警告的情况下进行编译,并严肃对待 - 例如如果您使用的是gcc,请使用-Wall -pedantic进行编译。
+1

你可能还想提一提,[这个程序处理较大的输入相当可怕](http://stackoverflow.com/q/1621394/274261)。 – ArjunShankar

+0

谢谢! strcmp是一个明显的错误,愚蠢的我。我不想返回任何东西,这个函数返回一个void *指针,因为我使用pthreads。 – Ormannishe

2

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

阵列上的使用引用操作*是一样的做得例如array[0],这意味着作为一个参数既scanfprintf要传递line[0],其如以上所解释的,是一个NULL指针。取消引用指针NULL,像scanfprintf会做,是未定义行为,一个几乎总是导致崩溃的情况。