2014-10-27 4 views
1

Эта функция находится в сервере сокетов. Когда клиент отправляет запрос, сервер берет запрос и находит совпадения из связанного списка. Функция работает отлично для первых нескольких запросов, а затем возникает ошибка сегментации. Проблема возникает при вызове sprintf (после «Before sprintf. \ N»). Я действительно не понимаю, почему это работает всего несколько раз. Что я сделал не так?Ошибка сегментации на sprintf в C

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'. –

+0

Эта строка: узел * temp = head; похоже, ссылается на переменную «голова», которая не определена. – user3629249

+0

такой вид линии: char * searchResult = calloc (1, sizeof (* searchResult)); вряд ли будет работать, потому что (в начале) searchResult не указывает на что-либо в частности, поэтому запрос на разыменованный размер, скорее всего, вернет 4, если что-нибудь полезное – user3629249

ответ

1

Вы забыли проверить успех calloc. И вы используете его неправильно: вам нужно выделить достаточное количество байтов для строки с нулевым завершением.

Обратите внимание, что 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. Используйте valgrind и отладчик gdb.

+1

Удивительно (в плохом смысле), как люди понятия не имеют о безопасных версиях функций stdlib и в массовом порядке предпочитают их опасные варианты. .. –

+0

Я бы сказал, что ОП просто забыл (?) Перераспределить то, что окончательный результ должен окончательно указывать. – alk

+0

Спасибо, что ответили. Но почему он работал на первые несколько звонков и в конечном итоге рушился? Меня это очень беспокоит. Если это не так, это не должно работать вообще. Но почему? Я застрял в этом несколько дней. Я все еще не понимаю. –

0

Вы являются регулировки, какие searchResult точки, но finalResult остается указывать только 1 char, хотя он, наконец, копируется результат все поиска в, что большинство Propably более 1 char с написания этой статьи к недопустимой памяти и провоцируя неопределенное поведение.

1

Я не знаю, что этот sprintf собирается делать, когда передано searchResult как аргумент. Страница на моей системе говорит о том, что это не определено:

C99 и POSIX.1-2001 указывает, что результаты не определены, если вызов к Sprintf(), snprintf(), vsprintf(), или vsnprintf() приведет к копированию между перекрываемыми объектами (например, если строковый массив целевого и один из входящих в него аргументов ввода относятся к тому же буфера).

Возможно, вы, скорее всего, будете использовать strcat.

1

только что прочитал неисправную линию

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

Он говорит печати SEARCHRESULT и другие вещи в SEARCHRESULT. Это, возможно, не могу работать

SEARCHRESULT не Tardis

Смежные вопросы