2012-12-28 39 views
4

我一直在爲學校開展一個項目(今晚到期!),而且我有一些嚴重的內存問題。我對C相當陌生,當涉及到mallocing指針和whatnot時,我仍然被拋出循環,所以我真的可以使用一些幫助。C鏈表中的內存泄漏

代碼如下。文件的順序是LinkedLists.h(LinkedList模塊的標題),LinkedLists.c(LinkedList模塊)和TestList.c(主模塊)。

/****************************************************************************** 
* Base struct to contain data structure element information: deterimined by 
* the application needs. 
******************************************************************************/ 
#ifndef _LINKED_LISTS_H_ 
#define _LINKED_LISTS_H_ 

typedef struct ElementStructs 
    { 
     int ElementPosition; 
     char* ElementValue; 
    } ElementStructs; 

/************** Nothing else in the module needs to be modified *************/ 



/****************************************************************************** 
* Base struct of list nodes, contains user information and link pointers. 
* The "ElementStructs" typemark must be defined based on specific needs of the 
* application. 
******************************************************************************/ 
typedef struct LinkedListNodes 
    { 
    /* The user information field */ 
    ElementStructs *ElementPtr; 
    /* Link pointers */ 
    struct LinkedListNodes *Next; 
    struct LinkedListNodes *Previous; 
    } LinkedListNodes; 

/****************************************************************************** 
* Base struct used to manage the linked list data structure. 
******************************************************************************/ 
typedef struct LinkedLists 
    { 
    /* Number of elements in the list */ 
    int NumElements; 
    /* Pointer to the front of the list of elements, possibly NULL */ 
    struct LinkedListNodes *FrontPtr; 
    /* Pointer to the end of the list of elements, possibly NULL */ 
    struct LinkedListNodes *BackPtr; 
    } LinkedLists; 

/****************************************************************************** 
* Initialized the linked list data structure 
******************************************************************************/ 
void InitLinkedList(LinkedLists *ListPtr); 

/****************************************************************************** 
* Adds a record to the front of the list. 
******************************************************************************/ 
void AddToFrontOfLinkedList(LinkedLists *ListPtr, ElementStructs *DataPtr); 

/****************************************************************************** 
* Adds a record to the back of the list. 
******************************************************************************/ 
void AddToBackOfLinkedList(LinkedLists *ListPtr, ElementStructs *DataPtr); 

/****************************************************************************** 
* Removes (and returns) a record from the front of the list ('works' even on 
* an empty list by returning NULL). 
******************************************************************************/ 
ElementStructs *RemoveFromFrontOfLinkedList(LinkedLists *ListPtr); 

/****************************************************************************** 
* Removes (and returns) a record from the back of the list ('works' even on 
* an empty list by returning NULL). 
******************************************************************************/ 
ElementStructs *RemoveFromBackOfLinkedList(LinkedLists *ListPtr); 

/****************************************************************************** 
* De-allocates the linked list and resets the struct fields as if the 
* list was empty. 
******************************************************************************/ 
void DestroyLinkedList(LinkedLists *ListPtr); 

#endif /* _LINKED_LISTS_H_ */ 

LinkedLists.c:

/****************************************************************************** 
* Extracts and prints the first and last 6 elements from the specified data 
* set and prints the total number of words in the input file. Utilizes the 
* LinkedList module as specified in LinkedLists.h 
* Written by xxxxxxx 
******************************************************************************/ 
#include <stdio.h> 
#include <stdlib.h> 
#include "LinkedLists.h" 

void InitLinkedList(LinkedLists *ListPtr) 
{ 
     ListPtr->NumElements = 0; 
     ListPtr->FrontPtr = NULL; 
     ListPtr->BackPtr = NULL; 
} 

void AddToFrontOfLinkedList(LinkedLists *ListPtr, ElementStructs 
     *DataPtr) 
{ 

     /* If there are no other elements, create new node and add it, 
     * assigning it to both the front and back pointers */ 
     if(ListPtr->NumElements == 0) 
     { 
       ListPtr->FrontPtr = malloc(sizeof(LinkedListNodes)); 
       ListPtr->FrontPtr->ElementPtr = DataPtr; 
       ListPtr->FrontPtr->Next = NULL; 
       ListPtr->FrontPtr->Previous = NULL; 
       ListPtr->BackPtr = ListPtr->FrontPtr; 
     } 

     /* If there are other elements, create new node and add it to the front 
     * while retaining previous node order */ 
     else 
     { 
       /* Initialize new LinkedListNode */ 
       ListPtr->FrontPtr->Previous = malloc(sizeof(LinkedListNodes)); 
       ListPtr->FrontPtr->Previous->ElementPtr = DataPtr; 
       ListPtr->FrontPtr->Previous->Next = ListPtr->FrontPtr; 
       ListPtr->FrontPtr->Previous->Previous = NULL; 

       /* Assign newly initialized node as front node of LinkedList */ 
       ListPtr->FrontPtr = ListPtr->FrontPtr->Previous; 
     } 

     /* List size plus one */ 
     (ListPtr->NumElements)++; 
} 

void AddToBackOfLinkedList(LinkedLists *ListPtr, ElementStructs 
     *DataPtr) 
{ 
     /* If there are no other elements, create new node and add it, 
     * assigning it to both the front and back pointers */ 
     if(ListPtr->NumElements == 0) 
     { 
       ListPtr->FrontPtr = malloc(sizeof(LinkedListNodes)); 
       ListPtr->FrontPtr->ElementPtr = DataPtr; 
       ListPtr->FrontPtr->Next = NULL; 
       ListPtr->FrontPtr->Previous = NULL; 
       ListPtr->BackPtr = ListPtr->FrontPtr; 
       /*printf("Adding %s\n", DataPtr->ElementValue);*/ 
     } 

     /* If there are other elements, create new node and add it to the back 
     * while retaining previous node order */ 
     else 
     { 
       /* Initialize new LinkedListNode */ 
       ListPtr->BackPtr->Next = malloc(sizeof(LinkedListNodes)); 
       ListPtr->BackPtr->Next->ElementPtr = DataPtr; 
       ListPtr->BackPtr->Next->Previous = ListPtr->BackPtr; 
       ListPtr->BackPtr->Next->Previous = ListPtr->BackPtr; 
       ListPtr->BackPtr->Next->Next = NULL; 

       /* Assign newly initialized node as back node of LinkedList */ 
       ListPtr->BackPtr = ListPtr->BackPtr->Next; 
       printf("Adding %s\n", ListPtr->BackPtr->ElementPtr->ElementValue); 
     } 

     /* List size plus one */ 
     (ListPtr->NumElements)++; 
} 

ElementStructs *RemoveFromFrontOfLinkedList(LinkedLists *ListPtr) 
{ 
     if(ListPtr->NumElements > 0) 
     { 
       ElementStructs *removedElement = ListPtr->FrontPtr->ElementPtr; 
       LinkedListNodes *removedNode = ListPtr->FrontPtr; 
       if(ListPtr->NumElements == 1) 
      { 
        ListPtr->FrontPtr = NULL; 
      } 
      else 
      { 
        ListPtr->FrontPtr = ListPtr->FrontPtr->Next; 
        ListPtr->FrontPtr->Previous = NULL; 
      } 
      (ListPtr->NumElements)--; 
      free(removedNode); 
      return removedElement; 
    } 
    else 
    { 
      ElementStructs *nullElement = NULL; 
      return nullElement; 
    } 
} 

ElementStructs *RemoveFromBackOfLinkedList(LinkedLists *ListPtr) 
{ 
     if(ListPtr->NumElements > 1) 
     { 
       ElementStructs *removedElement = ListPtr->BackPtr->ElementPtr; 
       LinkedListNodes *removedNode = ListPtr->BackPtr; 
       if(ListPtr->NumElements == 1) 
       { 
         ListPtr->BackPtr = NULL; 
       } 
       else 
       { 
         ListPtr->BackPtr = ListPtr->BackPtr->Previous; 
         ListPtr->BackPtr->Next = NULL;  
       } 
       (ListPtr->NumElements)--; 
       free(removedNode); 
       return removedElement; 
     } 
     else 
     { 
       ElementStructs *nullElement = NULL; 
       return nullElement; 
     } 
} 


void DestroyLinkedList(LinkedLists *ListPtr) 
{ 
     while(ListPtr->FrontPtr != NULL) 
     { 
       LinkedListNodes *removedNode = ListPtr->FrontPtr; 
       ListPtr->FrontPtr = ListPtr->FrontPtr->Next; 

       /* Deallocate element in node */ 
       free(removedNode->ElementPtr->ElementValue); 
       free(removedNode->ElementPtr); 

       /* Deallocate node */ 
       free(removedNode); 
     } 
     free(ListPtr); 
} 

TestList.c:

/****************************************************************************** 
* Tests the functionality of the LinkedList specified in LinkedLists.h using 
* the file "american-english-words". Reads in individual words and stores them 
* as node elements in the LinkedList. 
* Written by xxxxx 
*****************************************************************************/ 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include "LinkedLists.h" 

#define MAX_LENGTH 100 /* Length of longest word in any major English dictionary */ 

int main(int argc, char** args) 
{ 
     if(argc == 2) 
     { 
       /* Initialize LinkedList */ 
       LinkedLists *LL; 

       /* File pointer to input file */ 
       FILE *fp; 

       /* Node to store input data from file */ 
       ElementStructs *NodeData; 

       /* Loop completion boolean */ 
       int Done; 

       /* Loop position counter */ 
       int Position; 

       /* Iterator */ 
       ElementStructs *CurElement; 

       /* Open input file and check that it is readable. If not, exit */ 
       fp = fopen(args[1], "r"); 

       if(fp == NULL) 
       { 
         fprintf(stderr, "File open failed."); 
         return 2; 
       } 

       /* Initialize linked list and other necessary variables */ 
       LL = malloc(sizeof(*LL)); 
       InitLinkedList(LL); 

       Done = 0; 
       Position = 0; 

       do 
       { 
         if(!feof(fp)) 
         { 
           /* Allocate space for new node data */ 
           NodeData = malloc(sizeof(ElementStructs)); 

           /* Allocate space in node element for input string */ 
           NodeData->ElementValue = malloc(MAX_LENGTH * sizeof(char)); 

           /* Read new node data from file */ 
           fscanf(fp, "%s", NodeData->ElementValue); 

           /* Assign scanned values to node elements */ 
           NodeData->ElementPosition = Position; 
           /*strcpy(NodeData->ElementValue, readString);*/ 

           /* Add data node to LinkedList */ 
           AddToFrontOfLinkedList(LL, NodeData); 
         } 
         else 
           Done = 1; 
         Position++; 
       }while(Done == 0); 

       do 
       { 
         CurElement = RemoveFromFrontOfLinkedList(LL); 

         if(CurElement != NULL) 
           printf("Word #%d: %s\n", CurElement->ElementPosition, 
           CurElement->ElementValue); 
       }while(CurElement != NULL); 

       /* Deallocate linked list */ 
       DestroyLinkedList(LL); 
       fclose(fp); 

     } 
     /* Bad command line input */ 
     else 
     { 
       fprintf(stderr, "Incorrect number of arguments"); 
       return 1; 
     } 

     return 0; 
} 

程序編譯罰款。但是,運行它會在執行結束時導致seg錯誤,並且valgrind會報告多個內存泄漏(如下所示)。請,如果你有任何幫助,我會非常感激。該問題主要在LinkedList.c模塊的RemoveFromBackOfLinkedList和RemoveFromFrontOfLinkedList方法中。主模塊(TestList.c)中有一段代碼調用了其中一個函數(我嘗試過這兩種函數,但它們具有幾乎相同的功能,並且都不起作用)。該塊是一個do /同時如下所示循環:

do 
       { 
       CurElement = RemoveFromFrontOfLinkedList(LL); 

         if(CurElement != NULL) 
           printf("Word #%d: %s\n", CurElement->ElementPosition, 
           CurElement->ElementValue); 
       }while(CurElement != NULL); 

Valgrind的結果:

Word #225921: stoich 
. 
. 
. 
. 
Word #6: Cam's 
Word #5: petrochemistry's 
Word #4: Tera 
Word #3: benedictions 
Word #2: wisted 
Word #1: toxins 
==4849== Invalid write of size 8 
==4849== at 0x400B5C: RemoveFromFrontOfLinkedList (in /home/amb2189/hw3/TestList) 
==4849== by 0x40085B: main (in /home/amb2189/hw3/TestList) 
==4849== Address 0x10 is not stack'd, malloc'd or (recently) free'd 
==4849== 
==4849== 
==4849== Process terminating with default action of signal 11 (SIGSEGV) 
==4849== Access not within mapped region at address 0x10 
==4849== at 0x400B5C: RemoveFromFrontOfLinkedList (in /home/amb2189/hw3/TestList) 
==4849== by 0x40085B: main (in /home/amb2189/hw3/TestList) 
==4849== If you believe this happened as a result of a stack 
==4849== overflow in your program's main thread (unlikely but 
==4849== possible), you can try to increase the size of the 
==4849== main thread stack using the --main-stacksize= flag. 
==4849== The main thread stack size used in this run was 8388608. 
==4849== 
==4849== HEAP SUMMARY: 
==4849==  in use at exit: 23,965,172 bytes in 413,185 blocks 
==4849== total heap usage: 619,775 allocs, 206,590 frees, 28,923,332 bytes allocated 
==4849== 
==4849== 16 bytes in 1 blocks are possibly lost in loss record 1 of 9 
==4849== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4849== by 0x4007E2: main (in /home/amb2189/hw3/TestList) 
==4849== 
==4849== 200 bytes in 2 blocks are possibly lost in loss record 5 of 9 
==4849== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4849== by 0x4007F0: main (in /home/amb2189/hw3/TestList) 
==4849== 
==4849== 23,963,992 (3,305,392 direct, 20,658,600 indirect) bytes in 206,587 blocks are definitely lost in loss record 9 of 9 
==4849== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4849== by 0x4007E2: main (in /home/amb2189/hw3/TestList) 
==4849== 
==4849== LEAK SUMMARY: 
==4849== definitely lost: 3,305,392 bytes in 206,587 blocks 
==4849== indirectly lost: 20,658,600 bytes in 206,586 blocks 
==4849==  possibly lost: 216 bytes in 3 blocks 
==4849== still reachable: 964 bytes in 9 blocks 
==4849==   suppressed: 0 bytes in 0 blocks 
==4849== Reachable blocks (those to which a pointer was found) are not shown. 
==4849== To see them, rerun with: --leak-check=full --show-reachable=yes 
==4849== 
==4849== For counts of detected and suppressed errors, rerun with: -v 
==4849== Use --track-origins=yes to see where uninitialised values come from 
==4849== ERROR SUMMARY: 5 errors from 5 contexts (suppressed: 2 from 2) 
Segmentation fault (core dumped) 
+0

花箱,哎喲。 – 2012-12-28 12:26:15

+0

教授的選擇,不是我自己的:p – SwarthyMantooth

+0

要找到段錯誤發生的位置,請在'gdb'和'bt'中運行以獲得回溯。 –

回答

3

讓你2種刪除功能的一些變化,,

ElementStructs *RemoveFromFrontOfLinkedList(LinkedLists *ListPtr) 
{ 
     if(ListPtr->NumElements > 0) 
     { 
     /*  ElementStructs *removedElement = ListPtr->FrontPtr->ElementPtr;*/ 
       /*LinkedListNodes *removedNode = malloc(sizeof(removedNode)); // no need allocate because you are deleting the node 
       removedNode = ListPtr->FrontPtr;*/ 
       LinkedListNodes *removedNode = ListPtr->FrontPtr; // use this line 
       ListPtr->FrontPtr = ListPtr->FrontPtr->Next; 
       ListPtr->FrontPtr->Previous = NULL; 
       free(removedNode); 
       (ListPtr->NumElements)--; 
       return NULL; 
     } 
     else 
     { 
       ElementStructs *nullElement = NULL; 
       return nullElement; 
     } 
} 

ElementStructs *RemoveFromBackOfLinkedList(LinkedLists *ListPtr) 
{ 
     if(ListPtr->NumElements != 0) 
     { 
       ElementStructs *removedElement = ListPtr->BackPtr->ElementPtr; 
       LinkedListNodes *removedNode = ListPtr->BackPtr; 
       ListPtr->BackPtr = ListPtr->BackPtr->Previous; 
       ListPtr->BackPtr->Next = NULL; 
       free(removedNode); 
       (ListPtr->NumElements)--; // add this line 
       return removedElement; 
     } 
     else 
     { 
       ElementStructs *nullElement = NULL; 
       return nullElement; 
     } 
} 

編輯1

CurElement = malloc(sizeof(*CurElement));這是main中的另一個mem漏洞,您不必爲它使用malloc,只需刪除此行。

編輯2:你爲什麼不釋放你的ELEMENT和ELEMENTVALUE ...?

do 
{ 
     CurElement = RemoveFromFrontOfLinkedList(LL); 

     if(CurElement != NULL) { 
       printf("Word #%d: %s\n", CurElement->ElementPosition, 
       CurElement->ElementValue); 
       free(CurElement->ElementValue); //add these 2 line to free ELEMENTVALUE And ELEMENT. 
       free(CurElement); 
     } 
}while(CurElement != NULL); 
+0

得到了這兩個,謝謝。我知道它問了很多,但你能看看Valgrind更新的問題嗎?有一些東西提出了一直困擾着我整夜的刪除方法(具體來說,在輸出結束時「無效寫入8號」) – SwarthyMantooth

+0

請參閱編輯2 ...可能有幫助 –

+0

沒有泄漏。你是天使,我的朋友。謝謝。 – SwarthyMantooth

5
==4769== 8 bytes in 1 blocks are definitely lost in loss record 1 of 4 
==4769== at 0x4C2B6CD: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==4769== by 0x400B46: RemoveFromFrontOfLinkedList (in /home/amb2189/hw3/TestList) 
==4769== by 0x400869: main (in /home/amb2189/hw3/TestList) 

這指的是以下代碼:

LinkedListNodes *removedNode = malloc(sizeof(removedNode)); 
removedNode = ListPtr->FrontPtr; 

malloc的方塊然後將內存分配給removedNode,然後立即覆蓋指針值。這不會分配給removedNode的內容,但會覆蓋指針。

CurElement = malloc(sizeof(*CurElement)); 

CurElement下使用立即覆蓋指針值,這意味着你失去了你的參考分配的內存:如所指出的Valgrind的


下一個內存泄漏發生在main

CurElement = RemoveFromFrontOfLinkedList(LL); 
+0

你對此是正確的,但這實際上是我嘗試修復我已經收到的錯誤的一次嘗試。刪除它後,我陷入了同樣的錯誤。此外,我還包括一些已在原始文章中更新的derp代碼。 非常感謝您的回覆,但絕對解決了我的許多問題之一:) – SwarthyMantooth

1

我覺得一個泄漏是從CurElement = malloc(sizeof(*CurElement));CurElement的下一次使用覆蓋了這個指針。

它也不能立即清除NodeData->ElementValue獲得釋放。

+0

它應該在DestroyLinkedList的while循環中釋放(在LinkedLists.c中) 是的,這是一個問題!謝謝! – SwarthyMantooth

1

你想要做什麼做:

LinkedListNodes *removedNode = malloc(sizeof(removedNode)); 
removedNode = ListPtr->FrontPtr; 

你的malloc一些空間和overwride指針

+0

是的,剛剛在Mike Kwan的幫助下解決了這個問題。謝謝回覆。 – SwarthyMantooth