C trie节点重新分配导致分段错误

时间:2015-09-29 20:57:34

标签: c io segmentation-fault trie calloc

我正在尝试实现一个拼写检查程序,一步是将字典加载到trie结构中。我已经使用GDB来确定,根据我的理解,每次尝试将current->children分配给值时,我都会遇到分段错误。底部的完整代码,但问题的方法:

bool load(const char* dictionary)
{
    FILE* dic = fopen(dictionary, "r");

    if(dic == false)
    {
        return false;
    }

    root = calloc(27, sizeof(node));
    node* current = NULL;
    /**for(int i=0;i<27;i++)
    {
        current->children[i]=NULL;
    }*/ //this will be the location of the segmentation fault if uncommented
    int a = 0;

    while((a = fgetc(dic)) != EOF)
    {
        if (a == '\n')
        {
            //this is the end of a word
            if(!current->is_word)
            {
                //duplicate case
                current->is_word = true;
                wordcounter++;
            }
            current = root;        
        }
        else
        {
            if(current->children[a-'a'] == NULL)
            {
                current->children[a-'a'] = calloc(27,sizeof(node));
            }
            current = current->children[a-'a'];
        }
    }
    if(current!= root && !current->is_word)
    {
        current->is_word = true;
        wordcounter++;
    }

    fclose(dic);
    return true;
}

在我检查了stackoverflow上的其他几个答案后,我尝试实现了注释代码,但这只会导致在for循环中发生分段错误。否则,它出现在if(current->children[a-'a']==NULL){...}

这里发生了什么?我以为calloc()会自动将分配的内存设置为0?我接触到的记忆是什么?我不应该这样做?

下面的完整.c:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

#include "dictionary.h"

typedef struct node
{
    bool is_word;
    struct node* children[27];
}
node;

node* root;
int wordcounter=0; 

 //Returns true if word is in dictionary else false.

bool check(const char* word)
{
    node* current = root;
    int b = 0;

    while(word[b] != '\n')
    {
        int letter = tolower(word[b]);

        if(letter == '\'')
        {
            return false;
        }

        if(current->children[letter-'a'] != NULL)
        {
            current = current->children[letter-'a'];
            b++;
        }
        else
        {
            return false;
        }
    }

    if(current->is_word == true)
    {
        return true;
    }   
    return false;
}


 // Loads dictionary into memory.  Returns true if successful else false.
bool load(const char* dictionary)
{
    FILE* dic = fopen(dictionary, "r");

    if(dic == false)
    {
        return false;
    }


    root = calloc(27, sizeof(node));
    node* current = NULL;
    /**for(int i=0;i<27;i++)
    {
        current->children[i]=NULL;
    }*/
    int a = 0;

    while((a = fgetc(dic)) != EOF)
    {
        if (a == '\n')
        {
            //this is the end of a word
            if(!current->is_word)
            {
                //duplicate case
                current->is_word = true;
                wordcounter++;
            }
            current = root;        
        }
        else
        {
            if(current->children[a-'a'] == NULL)
            {
                current->children[a-'a'] = calloc(27,sizeof(node));
            }
            current = current->children[a-'a'];
        }
    }
    if(current!= root && !current->is_word)
    {
        current->is_word = true;
        wordcounter++;
    }

    fclose(dic);
    return true;
}


//Returns number of words in dictionary if loaded else 0 if not yet loaded. 
unsigned int size(void)
{
    return wordcounter;
}


 //Unloads dictionary from memory.  Returns true if successful else false. 
void memFree(node* current)
{
    for(int i = 0; i < 27; i++)
    {
        if(current->children[i] !=NULL)
        {
            memFree(current->children[i]);
        }
    }
    free(current);
}

bool unload(void)
{
    memFree(root);    
    return true;
}

1 个答案:

答案 0 :(得分:2)

发生错误是因为您正在初始化current = NULL,然后取消引用它(current->children)。它是一个直线空指针解除引用。

查看其余代码,您可能打算

node *current = root;

代替。