2013-02-16 59 views
0

我很難弄清楚我的程序出了什麼問題。我正在嘗試通過在createNode函數中創建節點,然後使用addNode將它們添加到列表頭部來創建鏈接列表。當我嘗試創建節點並且出現分段錯誤時,程序失敗。malloc問題,C中的內存泄漏

#include<stdlib.h> 
#include<stdio.h> 
#include<string.h> 
#include "list.h" 

struct listnode { 
    int line; 
    char *word; 
    struct lnode *next; 
}; 


struct listnode* createNode (char* word, int line) { 
    int strlen1 = strlen(word)+1; 
    struct lnode *node = malloc(sizeof(struct lnode)); 
    node->word = malloc(sizeof(char)*strlen1); 
    strcpy(node->word,word); 
    node->word[strlen1] = '\0'; 
    node->next = NULL; 
    node->line = line; 
    return node; 
} 


void addNode (struct listnode** head, struct listnode* node) { 
    if ((*head)==NULL){ 
    head = &node; 
    } 
    else if((*head)->next!=NULL){ 
     struct lnode *temp = *head; 
     node->next = *head; 
    }else if(*head!=NULL&&(*head)->next==NULL){ 
     (*head->next) = node; 
    } 
    } 

通過運行Valgrind的程序產生以下錯誤:

==14661== Command: ./testlist 
==14661== 
==14661== Invalid write of size 1 
==14661== at 0x4006E3: createNode (in /u/data/u95/testprogs/testlist) 
==14661== by 0x40091C: main (in /u/data/u95/testprogs/testlist) 
==14661== Address 0x51dc0a6 is 0 bytes after a block of size 6 alloc'd 
==14661== at 0x4C2AF5D: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64 linux.so) 
==14661== by 0x4006AF: createNode (in /u/data/u95/testprogs/testlist) 
==14661== by 0x40091C: main (in /u/data/u95/testprogs/testlist) 
==14661== 
==14661== Use of uninitialised value of size 8 
==14661== at 0x40071C: addNode (in /u/data/u95/testprogs/testlist) 
==14661== by 0x400933: main (in /u/data/u95/testprogs/testlist) 
==14661== Uninitialised value was created by a stack allocation 
==14661== at 0x4008E8: main (in /u/data/u95/testprogs/testlist) 
==14661== 
==14661== Invalid read of size 8 
==14661== at 0x40071C: addNode (in /u/data/u95/testprogs/testlist) 
==14661== by 0x400933: main (in /u/data/u95/testprogs/testlist) 
==14661== Address 0x0 is not stack'd, malloc'd or (recently) free'd 
==14661== 
==14661== 
==14661== Process terminating with default action of signal 11 (SIGSEGV) 
==14661== Access not within mapped region at address 0x0 
==14661== at 0x40071C: addNode (in /u/data/u95/testprogs/testlist) 
==14661== by 0x400933: main (in /u/data/u95/testprogs/testlist) 
==14661== If you believe this happened as a result of a stack 
==14661== overflow in your program's main thread (unlikely but 
==14661== possible), you can try to increase the size of the 
==14661== main thread stack using the --main-stacksize= flag. 
==14661== The main thread stack size used in this run was 8388608. 

我是新的C和我不知道爲什麼被拋出這些錯誤。有人可以幫忙嗎?

+0

您不需要將終止符添加到'createNode'中的字符串,它是由'strcpy'自動完成的。 – 2013-02-16 19:34:02

+0

向我們展示'main'中的代碼。你有至少1個堆棧上的節點嗎? – 2013-02-16 19:35:41

+0

在函數'addNode'中,語句'head = &node;'將局部變量'node'的地址賦給'head'。 'node'對於函數'addNode'是局部的 – sgarizvi 2013-02-16 19:35:46

回答

1

我找不到lnode的定義。是否與listnode相同?

addNode錯誤地設置頭元素並且沒有正確地找到長列表的尾部。它應該像

void addNode(struct listnode** head, struct listnode* node) { 
    if ((*head)==NULL){ 
     *head = node; 
    } 
    else { 
     struct listnode* tail = *head; 
     while (tail->next != NULL) { 
      tail = tail->next; 
     } 
     tail->next = node; 
    } 
} 

你失蹤的*head賦值爲一個空列表。設置head的值改變了本地指針,但不改變調用者的指針。對於更長的列表,您需要遍歷所有成員以查找尾部。

這可能會修復您的Use of uninitialised value of size 8錯誤。如果沒有,你需要告訴我們代碼addNode

createNode可以簡化word分配/初始化到

node->word = malloc(strlen(word)+1); 
strcpy(node->word,word); 

你並不需要設置一個空終止 - strcpy會複製這個給你。而且,正如William Pursell所指出的那樣,這實際上是一個重要的改變,因爲它避免了你在字符串末尾寫作。這將修復您的Invalid write of size 1錯誤。

1

以下是保證是錯誤的:

node->word = malloc(sizeof(char)*strlen1); 
... 
node->word[strlen1] = '\0'; 

你的字分配strlen1字節,所以你可能是指:

node->word[strlen1 - 1] = '\0'; 

注意,你甚至都不需要編寫一個空字節,因爲strcpy是爲你做的。目前還不清楚代碼中有哪些其他錯誤,在修復此錯誤之前並不值得尋找。

+0

Yay for heapoverflows :) – SecurityMatt 2013-02-16 19:42:36