2014-10-27 196 views
1

此函数位于套接字服务器中。当客户端发送查询时,服务器接受查询并从链接列表中查找匹配项。该功能适用​​于前几个查询,然后发生分段错误。问题发生在sprintf调用(“之前的sprintf。\ n”)之后。我真的不明白为什么它只是几次。我做错了什么?C中的sprintf出现分段错误

char* searchNode(char* query) { 
    int i, isFound, count = 0; 
    node* temp = head; 
    char* searchResult = calloc(1, sizeof(* searchResult)); 
    char* finalResult = calloc(1, sizeof(* finalResult));; 

    printf("Before search node.\n"); 

    while(temp->next) { 
     isFound = TRUE; 
     temp = temp->next; 
     for(i = 0; i < strlen(query); i++) { /* compare each char in both strings */ 
      if(tolower(query[i]) != tolower(temp->foodName[i])) { 
       isFound = FALSE; 
       break; 
      } 
     } 
     if(isFound == TRUE) { /* if a match is found, write it into the temp string */ 
     printf("Match found.\n"); 
      searchResult = realloc(searchResult, strlen(searchResult) + 1 + strlen(nodeToString(temp)) + 1); 
     printf("Before sprintf.\n"); 
      sprintf(searchResult, "%s%s", searchResult, nodeToString(temp)); 
      count++; /* count the number of results found */ 
     } 
    } 

    printf("Before finalise string.\n"); 

    if(count > 0) { /* if at least a result is found, add combine all results with a head line*/ 
     sprintf(finalResult, "%d food item(s) found.\n\n", count); 
     strcat(finalResult, searchResult); 
     free(searchResult); 
     return finalResult; 
    } 

    /* if no match is found, return this message */ 
    return "No food item found.\nPlease check your spelling and try again.\n"; 
} 
+3

您试图将字符串打印到自身中。如果你想追加一个字符串到另一个字符串,可以考虑使用'strcat'或'strncat'。 – 2014-10-27 17:21:01

+0

这一行:node * temp = head;似乎是引用了一个未定义的变量“head”。 – user3629249 2014-10-27 21:49:05

+0

这种类型:char * searchResult = calloc(1,sizeof(* searchResult));是不太可能的,因为(在开始时)searchResult没有指向任何特别的东西,所以要求取消引用的大小最有可能返回4,如果有用的话 – user3629249 2014-10-27 21:52:42

回答

1

你忘了测试calloc的成功。并且您正在错误地使用它:您需要为其中以0结尾的字符串分配足够的字节。

注意 char* searchResult = calloc(1, sizeof(* searchResult)); 是极其错误的:它相当于/* wrong code*/ char* searchResult= calloc(1,1);,你不能这样做,(你需要分配一个足够宽的字符串);你有一些undefined behavior,你有运气不好,它不会崩溃(SO包含很多关于UB的回答,见例如this one)。

您应该使用snprintf(3)(或许与strdup(3)),并且您应该考虑终止零字节的结果snprintf + 1。如果您的系统提供了它,您可能需要使用asprintf(3)

请编译所有警告和调试信息gcc -Wall -Wextra -g。使用valgrindgdb调试器。

+1

这真是太神奇了(在坏的意义上)人们不知道stdlib函数的安全版本,并且大量地偏好它的危险变体。 .. – 2014-10-27 17:21:42

+0

我想说OP只是忘了(?)来重新分配'finalResult'最终会指向什么。 – alk 2014-10-27 17:23:49

+0

感谢您的回答。但为什么它会在前几次调用中起作用并最终崩溃?这让我非常困扰。如果不对,它根本不应该工作。但为什么?我一直坚持这几天。我仍然不明白。 – 2014-10-27 17:35:42

0

调整什么searchResult点,但finalResult住宿指向只有1 char,虽然它最终被复制所有的搜索结果之中,其中大部分propably更多的是1 char,与此写入无效的内存和引发未定义的行为。

1

我不知道当传递searchResult作为参数时,sprintf会做什么。我的系统上的手册页顾名思义是未定义:

C99和POSIX.1-2001指定的结果是不确定的,如果通话 到的sprintf()的snprintf(),vsprintf中(),或vsnprintf ()将导致复制 发生在重叠的对象之间(例如,如果目标 字符串数组和一个提供的输入参数指向相同的 缓冲区)。

您应该使用strcat代替。

1

刚读失败线

sprintf(searchResult, "%s%s", searchResult, nodeToString(temp)); 

它说的打印信息搜索结果和其他东西进入信息搜索结果。它不可能工作

searchResult不是Tardis