通过遍历C中的链表进行分段错误?

时间:2015-09-14 18:13:05

标签: c segmentation-fault

我对C比较陌生,正在开发一个程序,用于创建地址信息的链接列表,按字母顺序按城市排序。当我尝试打印列表(只是名称和城市)时,我每次都会遇到一个特定条目的分段错误,大约是列表中的3/4。我使用fgets从文件中逐行读取数据,但我遇到的一个问题是“City State Zip”都是以这种格式排在一行,但我只想打印这个城市。此代码遍历已创建的链接条目列表,并尝试按顺序打印每个条目的名称和城市。我可以浏览并打印名称,但是当我尝试做城市时,其中一个条目就是给出了段错误。由于一些城市是两个单词,我不得不把代码放在那里(这就是为什么我有这四个单词 - 这可能是一个更好的方法,但这就是我的想法)

void printList() {
    struct addressEntry *current = head;

    while (current != NULL) {
        char *end;

        end = current->firstName + strlen(current->firstName) - 1;
        while (end > current->firstName && isspace(*end)) end--;
        *(end + 1) = 0;

        end = current->lastName + strlen(current->lastName) - 1;
        while (end > current->lastName && isspace(*end)) end--;
        *(end + 1) = 0;

        char * myCity = (char *) malloc(sizeof(char));

        char* firstWord = strtok(current->city," ");
        char* secondWord = strtok(NULL, " ");
        char* thirdWord = strtok(NULL, " ");
        char* fourthWord = strtok(NULL, " ");

        printf("Created four words from white spaces: %s_%s_%s_%s_\n", firstWord, secondWord, thirdWord, fourthWord);

        myCity = (char *) realloc(myCity, 2 + strlen(firstWord) + strlen(secondWord));

        if (strlen(fourthWord) != 5) {
            printf("Made it to one-word city\n");
            myCity = firstWord;
        }
        else {
            printf("Made it to two-word city\n");
            strcpy(myCity, firstWord);
            strcat(myCity, " ");
            strcat(myCity, secondWord);
            printf("Finished two word city: %s\n",myCity);
        }

        current = current->nextEntry;
    }
}

在调用realloc()函数后发生分段错误。当printf()调用打印导致segfault的特定条目执行四个单词中的每一个时,它看起来像这样:

Tampa_NC_28211
_(null)_

我不明白指针疯狂,所以我一直很困惑,为什么只是这个条目不起作用,我可以做些什么来解决它。我已经尝试在realloc()之后添加一个if语句来检查fourthWord是否为NULL,但它从未输入过static state **symbols; 。有关如何避免segfault的任何帮助吗?

1 个答案:

答案 0 :(得分:0)

strtok()函数的第一个参数为NULL并且输入字符串中没有其他标记时,NULL函数返回NULL。你没有测试;如果发生这种情况,您只需在其中一个变量中记录NULL即可。因此,如果您遇到包含少于四个令牌的城市行,您将最终在printf()个参数中传递至少一个malloc()。这将产生未定义的行为,并且您观察到的失败可能是实际结果。

更一般地说,如果您确实关心是否发生错误,则应始终检查错误条件的函数返回值,并且通常应该关注是否发生错误。例如,在提供的代码中,除了realloc()之外,还应检查strtok()printf()的返回值。您还可以查看myCity的返回值,但在这种情况下,您可能不太关心这些值。

另外,正如@melpomene首次观察到的那样,你分配(然后重新分配)内存,但永远不会释放它。当变量JsonArray jsonArray = jsonObject["Groups"].GetArray(); 在循环的每次迭代结束时超出范围时,或者在为其分配新值时更早,您将丢失指向该分配内存的唯一指针。这构成了内存泄漏。但是,泄漏内存通常不会导致分段错误。