Ошибка сегментации в связанном списке - PullRequest
3 голосов
/ 13 января 2012

Редактировать: ответ Дейкстры - это способ решить эту проблему. Мой список не был инициализирован как NULL

Я работаю над связанным списком, чтобы сохранить уникальный список слов, который вызывает ошибки при попытке просмотреть список. ГБД дает мне:

    Program received signal SIGSEGV, 
    Segmentation fault. 0x0000003a07e47ff7 in vfprintf () from /lib64/libc.so.6 
    Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.7.el6_0.5.x86_64

Код вставки для списка:

typedef struct L { char x[40] ; int occ; struct L *next ;} List;
List *insertList( char *in, List *l )
{
    List *t = calloc( 1, sizeof( List ) ) ;
    strcpy(t->x, in);
    t->occ = 1;
    t->next = l ;
    return t ;
}

void printList(List *l)
{
    List *l2 = l;
    while(l2)
    {
        printf("%s ", l2->x);
        l2 = l2->next;
    }
    return;
}

Это перебирает слова, вставляя их в связанный список, вроде бы нормально. Когда я перебираю список для отображения слов (из примерно 4200 слов), примерно 98% ish будет отображаться нормально, а затем будет segfault без предупреждения.

С еще одним осмотром, он читает слова в обратном порядке, к которому они были добавлены (что имеет смысл), и достигнет примерно 5-го слова от конца списка (5-е слово добавлено) до сегфагинга. Я попытался настроить функцию вставки так, чтобы она содержала строки длиной более 40 символов, но все слова, вставляемые в начале (и содержащие сегменты), не превышают 20 символов.

При еще большем копании, если я напечатаю l2-> next-> next-> next-> next в функции printList, первые вставленные слова будут там.

Может ли кто-нибудь указать мне правильное направление с этим?

Спасибо

Ответы [ 4 ]

3 голосов
/ 13 января 2012

GDB (или другой отладчик, если вы не используете Linux) - мой предпочтительный инструмент для отслеживания ошибок сегментаСкомпилируйте код с символами отладки и запустите его в отладчике.При сбое осмотрите линию, которая вызывает сбой.При необходимости используйте команду backtrace.Выполнение этих шагов в значительной степени всегда показывает мне, как исправить ошибку segfault.

2 голосов
/ 13 января 2012

Это стилистическое замечание (которое не оценят люди SO; - [) Что не так с простым циклом for? Почему вы выполняете итерацию внутри цикла, когда для такого рода вещей есть действительная идиоматическая конструкция?

void printList(List *lp)
{
    List *l2;

    for(l2=lp; l2; l2 = l2->next)
    {
        printf("%s ", l2->x);
    }
    return;
}
2 голосов
/ 13 января 2012

Как вы инициализируете свой первый узел?

Вы говорите, что "первые несколько слов вызывают ошибку сегмента", но прерывание может остановить их печать, и проблема на самом деле приближается к самому концу.

Моя гипотеза (и на самом деле это всего лишь предположение: P) состоит в том, что ваш первый узел не имеет next = NULL;, это просто неинициализированная память. Поэтому цикл while не обнаруживает, что он достиг конца списка, и пытается распечатать что-то странное, что приведет к ошибке segfault.

2 голосов
/ 13 января 2012

Моим лучшим предположением будет то, что strncpy вместо strcpy исправит вашу проблему, похоже, что что-то перезаписало ваш «следующий» указатель где-то в конце списка, и слишком длинная строка в «in» наверняка это сделает.

Не забывайте, что strncpy не заканчивает слишком длинные строки, поэтому убедитесь, что вы поставили

x[39]=0;

, чтобы убедиться, что строка будет правильно завершена.

...