2017-06-19 23 views
0

我寫了一個拼寫檢查程序,它使用trie來存儲和檢查拼寫錯誤的單詞。它將文本文件字典加載到內存中,接受單詞以檢查拼寫錯誤並卸載內存。程序編譯成功,但運行時會產生分段錯誤。基於valgrind,問題似乎是在我的插入函數中使用未初始化的值。在拼寫檢查器中使用未初始化的大小爲8的值

//If word not present, inserts word into trie 
//If the word is a prefix of a node, marks the "leaf node" (end-of-word node) 
void insert(struct node *root, const char *word) 
{ 
int length = strlen(word); 
int index = 0; 

//start from root node 
struct node *tempNode = root; 

for(int i = 0; i < length; i++) 
{ 
    //if the current letter in word is a letter 
    if(word[i] != '\'') 

     //convert the alphabet to it's respective index number 
     index = CHAR_TO_INDEX(tolower(word[i])); 

    else 
     //assign index number 27 (for apostrophe) 
     index = INPUT_SIZE; 

    //create a new node if path doesn't exist (is NULL) 
    if(!(tempNode->children[index])) 
     tempNode->children[index] = getNode(); 

     //go to next node 
     tempNode = tempNode->children[index]; 
     } 
    //mark last node as leaf 
    tempNode->isWord = true; 
} 

刀片(在線索地方字)由負載稱爲(運動從詞典txt文件字到內存):

bool load(const char *dictionary) 
{ 
//initialise variables 
char ch; 
char word[LENGTH] = ""; 
int counter = 0; 

struct node *root = getNode(); 

//open file to start inserting words 
FILE *file = fopen(dictionary, "r"); 

//load words in dictionary into memory 
while (EOF) 
{ 
    while((ch = fgetc(file)) != '\n') 
    { 
     word[counter] = ch; 
     counter++; 
    } 
    //whole word found, insert word and reset counter, increment word count 
    insert(root, word); 
    counter = 0; 
    word_Count++; 
} 

//close all open files if EOF is reached, else loading has failed- return false 
if(EOF == true) 
    { 
    fileLoaded = true; 
    fclose(file); 
    return true; 
    } 
else return false; 
} 

和getNode(),它創建了一個新的節點初始化爲NULL:

//Returns new trie node initialised to NULL 
    struct node *getNode(void) 
    { 
    //initialise new node 
    struct node *newNode = NULL; 

    newNode = malloc(sizeof(struct node)); 

    //proceed if enough memory to allocate 
    if(newNode) 
    { 
    //initialise pointers 
    for(int i = 0; i < INPUT_SIZE; i++) 
     newNode->children[i] = NULL; 

    newNode->isWord = false; 
    } 
    else return false; 

    return newNode; 
    } 

結構節點的定義:

//Returns new trie node initialised to NULL 
struct node *getNode(void) 
{ 
    //initialise new node 
    struct node *newNode = NULL; 

    newNode = malloc(sizeof(struct node)); 

    //proceed if enough memory to allocate 
    if(newNode) 
    { 
     //initialise pointers 
     for(int i = 0; i < INPUT_SIZE; i++) 
      newNode->children[i] = NULL; 

     newNode->isWord = false; 
    } 
    else return false; 

    return newNode; 
} 

根據Valgrind的誤差:

Conditional jump or move depends on uninitialised value(s) 
==9334== at 0x4011DD: insert (dictionary.c:84) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 
==9334== Uninitialised value was created by a heap allocation 
==9334== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==9334== by 0x4010CB: getNode (dictionary.c:40) 
==9334== by 0x4011E7: insert (dictionary.c:85) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 
==9334== 
==9334== Use of uninitialised value of size 8 
==9334== at 0x4011D5: insert (dictionary.c:84) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 
==9334== Uninitialised value was created by a heap allocation 
==9334== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==9334== by 0x4010CB: getNode (dictionary.c:40) 
==9334== by 0x4011E7: insert (dictionary.c:85) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 
==9334== 
==9334== Invalid read of size 8 
==9334== at 0x4011D5: insert (dictionary.c:84) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 
==9334== Address 0x91 is not stack'd, malloc'd or (recently) free'd 
==9334== 
==9334== 
==9334== Process terminating with default action of signal 11 (SIGSEGV) 
==9334== Access not within mapped region at address 0x91 
==9334== at 0x4011D5: insert (dictionary.c:84) 
==9334== by 0x4014D1: load (dictionary.c:188) 
==9334== by 0x40095D: main (speller.c:40) 

的valgrind用--leak校驗=完全,--leak校驗=充分運行和--show泄漏-種=所有。我曾嘗試引用以前帖子中的類似錯誤,但上下文的差異使得難以確定我應該做什麼。第84行是讀取if(!(tempNode-> children [index]))的行。這似乎(對我而言)是問題的根源。

謝謝!

+0

您的調試器可能會告訴您更多 –

+1

什麼是struct node?兒童是指針的數組嗎? – Elan

+0

[MCVE]在這裏可能會有所幫助。 –

回答

0
while((ch = fgetc(file)) != '\n') 
{ 
    word[counter] = ch; 
    counter++; 
} 
//whole word found, insert word and reset counter, increment word count 
insert(root, word); 

這是導致未定義行爲的代碼的一部分。

您的字符串word不是空終止,但insert希望它是(因爲它做的第一件事就是調用strlen這需要一個空值終止字符串)。

簡單的解決方法是

word[counter] = '\0'; 
呼叫前

insert假設一切都在發展。