检查指针时的分段错误

时间:2016-01-31 23:54:39

标签: c segmentation-fault

我正在编写一个程序,它读取一个字典文件(文本文件,每行一个单词),并将其插入到由数组的“链表”组成的结构中,其中该单词以递归方式转发到[第一个字母] - 'a']数组的条目(这是另一个数组,处理下一个字母)。当整个单词被“消耗”时,它将单词(未更改)插入到常规的单词列表中。该程序成功处理前15个单词,但在第16个单词时会抛出分段错误。

以下代码段中的add()方法中出现了分段错误:

struct LinkedList * new = (struct LinkedList *) calloc(1,
                                       sizeof(struct LinkedList));
            if (!new) {
                perror("Not enough memory!"); // Error here
                exit(2);
            }

(希望)相关代码:

void addList (struct LinkedList * list, char * word) {
    if (!list->next)
    {
        struct LinkedList * new = malloc(sizeof(struct LinkedList));
        if (!new) {
            perror("Not enough memory!");
            exit(2);
        }

        char * new_word = malloc(strlen(word) * sizeof(char));
        if (!new_word) {
            fprintf(stderr, "Not enough memory!");
            exit(2);
        }


        new->next = 0;
        strcpy(new_word, word);
        new->word = new_word;
        list->next = new;
    }
    else
    {
        addList(list->next, word);
    }
}


void add(struct HashTree * root, char * word, char * word_sorted, int length) {

    if (length == 0)                                     // Found the correct place
    {

        if (!root->words)                                // If words are not allocated
        {
            // Create list node
            struct LinkedList * new = calloc(1, sizeof(struct LinkedList));
            if (!new) {
                perror("Not enough memory!");
                exit(2);
            }

            char * new_word = malloc(strlen(word) * sizeof(char));
            if (!new_word) {
                fprintf(stderr, "Not enough memory!");
                exit(2);
            }

            new->next = 0;

            strcpy(new_word, word);

            new->word = new_word;
            root->words = new;
        }   

        else                                            // Add to the Linked List
        {
            addList(root->words, word);
        }
    }

    else 
    {
        // printf("Length_add = %d\n", length);
        if (!root->next)                                 // If the array was not allocated yet
        {

            struct HashTree * new = malloc(27 * sizeof(struct HashTree *));
            if (!new) {
                perror("Not enough memory!");
                exit(2);
            }


            root->next = new;
        }


        add(&(root->next[ word_sorted[0] - 'a' ]), 
            word, (char *) (word_sorted +1), (length-1));  // Use the next letter.

    }


}

要保存空间Here is the link to the full code.

这是gdb core和backtrace的输出:

    Program terminated with signal SIGSEGV, Segmentation fault. 

100 perror("Not enough memory!"); 

Full GDB output

之前我在Java中实现了类似的算法,算法似乎是正确的。我对C很陌生,不明白可能出错。我真的很感激任何帮助!

编辑: 删除sort,clean和cleanWords方法(它们不会极大地影响将单词添加到结构中)。处理第二个单词时发生了分段,第125行:

perror("Dictionary file not found!");

Link to code -
Link to sample dictionary

Valgrind output

2 个答案:

答案 0 :(得分:2)

else的主add()子句中,您会分配一些内存,但不要初始化它。然后在下一次递归调用add()时使用未初始化的内存。至少使用calloc()代替malloc()。你还为你的结构分配了27个指针,但是你正在使用它,好像你分配了27个结构一样。

错:

struct HashTree * new = malloc(27 * sizeof(struct HashTree *));

右:

struct HashTree *new = calloc(27, sizeof(struct HashTree));

或者:

struct HashTree *new = calloc(27, sizeof(*new));

此外,在addList()add()中,您没有为字符串分配足够的空间;你忘记了尾随的空格。

错:

char *new_word = (char *) malloc(length * sizeof(char));

右:

char *new_word = (char *) malloc(length + 1);

我不会在我的C代码中使用C ++关键字,因此我会使用new_hash或其左右而不只是new。许多人会因为分配的演员而鞭挞你。

通过这些更改,代码对我来说已经完成了。它像愤怒一样泄露,但这完全是预期的。

答案 1 :(得分:0)

对于这样的错误,问题几乎总是fopen的问题。如果我是对的,您可能忘记将扩展名添加到文件中,或者这可能是您正在使用的文件路径的问题。

我的建议:

使用ctrl + f查找"/usr/share/dict/words"的所有实例,然后验证它们是否引用了正确的文件。

修改 要特别注意第184行。我怀疑"/usr/share/dict/words.txt"应该是while(fgets(word, sizeof(word), dict) != NULL) {

编辑2:

而不是(第200行):

while(!feof(dict)) {
    fscanf(dict, "%*[^']", MAX_WORD_LENGTH, word);

尝试fscanf

int fscanf( FILE *restrict stream, const char *restrict format, ... );

修改

谢谢@JonathanLeffler我仍然会推荐fscanf

fscanf

如果使用得当,fscanf(dict, "%*s", MAX_WORD_LENGTH, word); fscanf(dict, "'", MAX_WORD_LENGTH, word);//get rid of the delimiter 在阅读格式化数据时非常有用。

{{1}}