2014-05-14 37 views
1

我在下面幾行代碼:C有助於解釋釋放calloc段錯誤

DocumentNode *docNode = NULL; 
initDocNode(docNode, docID, wordFreq); 

這裏的initDocNode功能

void initDocNode(DocumentNode *docNode, int docID, int wordFreq) { 
    docNode = calloc(1, sizeof(DocumentNode)); 
    if (!docNode) 
     fprintf(stderr, ....); 
    docNode->docID = docID; 
    docNode->wordFrequency = wordFreq; 
} 

我有一個while循環創建docNodes,但在一點上,我用以下回溯獲得段錯誤。它看起來像是在calloc中發生的事情。任何幫助理解這一點將不勝感激。

_int_malloc ([email protected]=0x396fbb8760 <main_arena>, [email protected]=16) 
at malloc.c:3718 
3718   set_head(remainder, remainder_size | PREV_INUSE); 
(gdb) backtrace 

_int_malloc ([email protected]=0x396fbb8760 <main_arena>, [email protected]=16) 
at malloc.c:3718 
0x000000396f88098a in __libc_calloc (n=<optimized out>, elem_size=<optimized out>) 
at malloc.c:3187 
0x0000000000402270 in initDocNode (docnode=0x0, docID=680, wordFreq=1) 
at ../util/indexerUtils.c:59 
0x000000000040147b in ReconstructIndex (hashtable=0x7fffc8c561f8, 
wordToAdd=0x1c3eab0 "mode", docID=680, wordFreq=1) at src/query_engine.c:337 
0x0000000000401209 in ReadFile (file=0x7fffc8c5932a "cs_lvl3.dat") 
at src/query_engine.c:267 
0x0000000000400eff in main (argc=2, argv=0x7fffc8c58998) at src/query_engine.c:147 

我有一組單詞,並且爲每個單詞創建包含單詞的文檔的docNodes。只有當我用一長串匹配文檔處理一個單詞時,我纔會得到這個seg錯誤。是否有限制,我可以calloc多少?

以下是讀取包含單詞及其匹配文檔的文件併爲數據創建散列表的函數。該文件的內容的格式爲: 字number_of_matching_docs DOC文檔wordFreq ... wordFreq

HashTable *ReadFile(char *file){ 
FILE *fp = fopen(file, "r"); 
if (!fp) { 
    fprintf(stderr, "Error: Couldn't open file %s for reloading.\n", file); 
    return NULL; 
} 

HashTable *hashtable = calloc(1, sizeof(HashTable)); 
if (!hashtable) { 
    fprintf(stderr, "Error: Couldn't allocate memory for hashtable.\n"); 
    return NULL; 
} 
char c; 
bool done = false; 
while (1){ 
    int wordLength = 0; 
    //keep reading until you find a space 
    //this is to determine the length of the word 
    while ((c = fgetc(fp)) != ' '){ 

     if (c == EOF){ 
      // but if c is EOF, then we're done reading the file     
      done = true; 
      // break out of the loop counting word lenght 
      break; 
     } 

     wordLength++; 
    } 

    if (done){ 
     // break out of loop reading file 
     break; 
    }    
    // now allocate memory for the word and null character 
    char *currWord = calloc(wordLength + 1, sizeof(char)); 
    if (!currWord){ 
     fprintf(stderr, "Failed to allocate memory to store %s\n", currWord); 
     continue; 
    } 
    //now reverse the pointer to the beginning of the word 
    fseek(fp, -(wordLength + 1), SEEK_CUR); 

    int numFiles; 
    // now read the word. If it's unsuccessful, then there's no more lines. exit 
    fscanf(fp, "%s %d", currWord, &numFiles); 
    printf("Processing %s\n", currWord); 
    int i = 0; 
    while (numFiles--) { 
     int docID; 
     int wordCount; 
     if (!fscanf(fp, " %d %d", &docID, &wordCount)) { 
      fprintf(stderr, "Error: Couldn't process document for word, %s.\n", currWord); 
      free(currWord); 
      continue; 
     } 
     if (!ReconstructIndex(&hashtable, currWord, docID, wordCount)) { 
      fprintf(stderr, "Error: Couldn't reconstruct index for word, %s\n", currWord); 
      free(currWord); 
      continue; 
     } 
     printf("%s: just processed %d document\n", currWord, i); 
     i++; 

    } 

} 
fclose(fp); 
return hashtable; 

}

這裏的ReconstructIndex()

int ReconstructIndex(HashTable **hashtable, char* wordToAdd, int docID, int wordFreq) { 
//get the hash index 
int hashIndex = JenkinsHash(wordToAdd, MAX_HASH_SLOT); 
// if hash index is not taken 
if ((*hashtable)->table[hashIndex] == NULL) { 
    // make document node 
    DocumentNode *newDocNode = NULL; 
    // newDocNode = initDocNode(newDocNode, docID, wordFreq); 
    initDocNode(&newDocNode, docID, wordFreq); 
    if (!newDocNode) { 
     fprintf(stderr, "Failed to make DocumentNode for %s.\n", wordToAdd); 
     return 0; 
    } 
    // make word node with this document node 
    WordNode *newWordNode = NULL; 
    newWordNode = initWordNode(newWordNode, wordToAdd, newDocNode); 
    if (!newWordNode) { 
     fprintf(stderr, "Failed to make WordNode for %s.\n", wordToAdd); 
     free(newDocNode); 
     return 0; 
    } 
    // make hash table node with this word node 
    HashTableNode *newHTNode = NULL; 
    newHTNode = initHashTNode(newHTNode, (void*)newWordNode, NULL); 
    if (!newHTNode) { 
     fprintf(stderr, "Failed to make HashTableNode for %s.\n", wordToAdd); 
     free(newDocNode); 
     free(newWordNode->word); 
     free(newWordNode); 
     return 0; 
    } 
    // put hashtablenode into table at the hash index 
    (*hashtable)->table[hashIndex] = newHTNode; 

    return 1; 
} 
// if hash index is taken 
else { 
    // find word 
    HashTableNode *currHTNode = (*hashtable)->table[hashIndex]; 
    int inHashTable = 0; 
    while (currHTNode) { 
     WordNode * currWordNode = (WordNode *)(currHTNode->hashKey); 
     if (strcmp(wordToAdd, currWordNode->word) == 0){ 
      inHashTable = 1; 
      break; 
     } 
     currHTNode = currHTNode->next; 
    } 
    // if word was found 
    if (inHashTable) { 
     WordNode *currWordNode = (WordNode *)(currHTNode->hashKey); 
     // add document to this word's listing in hash index 
     // make new document node 
     DocumentNode *newDocNode = NULL; 
     // newDocNode = initDocNode(newDocNode, docID, wordFreq); 
     initDocNode(&newDocNode, docID, wordFreq); 
     if (!newDocNode) { 
      fprintf(stderr, "Failed to make DocumentNode for %s.\n", wordToAdd); 
      return 0; 
     } 
     // append this new doc node to back of other document nodes 
     DocumentNode *lastDocNode = currWordNode->doc; 

     while (lastDocNode->next) { 
      lastDocNode = lastDocNode->next;    
     } 

     lastDocNode->next = newDocNode; 
     // free(wordToAdd);  // causes seg fault 
     return 1; 
    } 
    // if word was not found 
    else { 
     // add word node to hashtable at this index 
     // make new document node 
     DocumentNode *newDocNode = NULL; 
     // newDocNode = initDocNode(newDocNode, docID, wordFreq); 
     initDocNode(&newDocNode, docID, wordFreq); 
     if (!newDocNode) { 
      fprintf(stderr, "Failed to make DocumentNode for %s.\n", wordToAdd); 
      return 0; 
     } 
     // make word node with this document node 
     WordNode *newWordNode = NULL; 
     newWordNode = initWordNode(newWordNode, wordToAdd, newDocNode); 
     if (!newWordNode) { 
      fprintf(stderr, "Failed to make WordNode for %s.\n", wordToAdd); 
      free(newDocNode); 
      return 0; 
     } 
     // make hash table node with this word node 
     HashTableNode *newHTNode = NULL; 
     newHTNode = initHashTNode(newHTNode, (void*)newWordNode, NULL); 
     if (!newHTNode) { 
      fprintf(stderr, "Failed to make HashTableNode for %s.\n", wordToAdd); 
      free(newDocNode); 
      free(newWordNode->word); 
      free(newWordNode); 
      return 0; 
     } 
     // append this new hashtable node to end of other hashtable nodes at hash index 
     HashTableNode *lastHTNode = (*hashtable)->table[hashIndex]; 
     while (lastHTNode->next) { 
      lastHTNode = lastHTNode->next; 
     } 
     lastHTNode->next = newHTNode; 
     return 1; 
    } 
} 

}

+1

你可以發佈while循環的代碼嗎?您可能會陷入無限循環並耗盡內存。 –

+0

我將在一秒內添加while循環。不過,我認爲我沒有一個無限循環。我添加了一個print語句來查看我的進度,並且我注意到在調用initDocNode獲取特定單詞的第678個文檔 – Stralo

+2

後發現了segfault。作爲一個附註,您的'initDocNode'函數對調用者沒有任何影響。指針是通過值傳遞的,所以'docNode ='賦值隻影響參數 - 它不會影響調用者中的變量。 –

回答

2

嘗試在函數體中使用** docNode而不是* docNode,因爲更改不會反映在函數體外。它在本地創建一個節點。 調用funcion pass參數爲& docNode。

+0

你的意思是將函數聲明爲void initDocNode(DocumentNode ** docNode,int docID,int wordFreq);'並用'initDocNode(&docNode,docID,wordFreq)調用它;'對嗎? –

+0

是的,通過這樣做,更改也將反映在呼叫點。 – Varun