是什么导致了我在C中的通用链表中的内存泄漏



我制作了自己的通用链表,但在我的removeStart和removeLast函数中,我不断地根据valgrind得到内存泄漏。有人能告诉我为什么会发生这种情况,以及可能的一些解决方案吗?

头文件:LinkedList.h

4 typedef struct LinkedListNode
5 {
6     void* data;
7     struct LinkedListNode* next;
8     struct LinkedListNode* previous;
9 } LinkedListNode;
10 
11 typedef struct
12 {
13     LinkedListNode* head;
14     LinkedListNode* tail;
15     int size;
16 } LinkedList;

代码:linkedlist.c

5 /*******************************************
6  * Name createLinkedList                   *
7  * Imports: none                           *
8  * Exports: list (LinkedList)              *
9  * Assertion: Creates a new linked list    *
10  ******************************************/
11 
12 LinkedList* createLinkedList()
13 {
14     LinkedList* list = (LinkedList*)malloc(sizeof(LinkedList));
15     list->head = NULL;
16     list->tail = NULL;
17     list->size = 0;
18 
19     return list;
20 }
21 
22 /****************************************************************
23  * Name: insertStart                                            *
24  * Imports: list (LinkedList*), entry (void*)                   *
25  * Exports: none                                                *
26  * Assertion: To insert a node at the beginning of the list     *
27  ***************************************************************/
28 
29 void insertStart(LinkedList* list, void* entry)
30 {
31     LinkedListNode* newNode = (LinkedListNode*)malloc(sizeof(LinkedListNode));
32 
33     newNode->data = entry;
34     newNode->next = list->head;
35     newNode->previous = NULL;
36 
37     if (list -> head == NULL)
38     {
39         list->head = newNode;
40         list->tail = newNode;
41         list->size++;
42     }
43     else
44     {
45         list->head = newNode;
46         newNode -> next -> previous = newNode;
47         list->size++;
48     }
49 
50 }
51 
52 /***********************************************************************
53  * Name: removeStart                                                   *
54  * Imports: list (LinkedList)                                          *
55  * Exports: none                                                       *
56  * Assertion: Deletes the first item, returns null if list is empty    *
57  **********************************************************************/
58 
59 void* removeStart(LinkedList* list)
60 {
61     LinkedListNode* curr = (LinkedListNode*)malloc(sizeof(LinkedListNode));
62 
63     void* ptr;
64 
65     curr = list->head;
66 
67     if (curr->next == NULL)
68     {
69         free(curr);
70         list->head = NULL;
71     }
72     if (curr->next != NULL)
73     {
74         ptr = curr -> data;
75 
76         list -> head = curr -> next;
77 
78         free(curr);
79         curr = NULL;
80 
81         list -> head -> previous = NULL;
82         list->size--;
83     }
84 
85 
86     return ptr;
87 }
88 
89 /************************************************************
90  * Name: insertLast                                         *
91  * Imports: list (LinkedList*), entry (void*)               *
92  * Exports: none                                            *
93  * Assertion: Imports an element to the back of the list    *
94  ***********************************************************/
95 
96 void insertLast(LinkedList* list, void* entry)
97 {
98     LinkedListNode* newNode = (LinkedListNode*)malloc(sizeof(LinkedListNode));
99     LinkedListNode* curr;
100 
101     if (list -> head == NULL)
102     {
103         insertStart(list, entry);
104     }
105     else
106     {
107         newNode->data = entry;
108         newNode->next = NULL;
109 
110         curr = list->head;
111 
112         while (curr->next != NULL)
113         {
114             curr = curr->next;
115         }
116 
117         if (curr->next == NULL)
118         {
119             curr->next = newNode;
120             newNode->previous = curr;
121         }
122 
123         list->tail = newNode;
124         list->size++;
125     }
126 
127 }
128 
129 /*************************************************************************************
130  * Name: removeLast                                                                  *
131  * Imports: list (LinkedList*)                                                       *
132  * Exports: ptr (void*)                                                              *
133  * Assertion: Removes an element from the end, if empty will return null pointer     *
134  ************************************************************************************/
135 
136 void* removeLast(LinkedList* list)
137 {
138     LinkedListNode* curr = list -> head;
139     LinkedListNode* secondLast;
140 
141     void* ptr;
142 
143     if (isEmpty(list) == 0)
144     {
145         printf("List is empty");
146     }
147     else
148     {
149         while (curr->next != NULL)
150         {
151             secondLast = curr;
152             curr = curr->next;
153         }
154 
155         if (curr == list->head)
156         {
157             list -> head = NULL;
158         }
159 
160     }
161 
162     ptr = curr->data;
163     list->size--;
164     secondLast -> next = NULL;
165     list -> tail = secondLast;
166 
167     free(curr);
168     curr = NULL;
169 
170     return ptr;
171 }
201 /******************************************************
202  * Name: freeLinkedList                               *
203  * Imports: list (LinkedList*), funcPtr (listFunc)    *
204  * Exports: none                                      *
205  * Assertion: To free all elements within the list    *
206  *****************************************************/
207 
208 void freeLinkedList(LinkedList* list)
209 {
210     LinkedListNode* curr;
211     LinkedListNode* next;
212 
213     curr = list->head;
214 
215     while (curr != NULL)
216     {
217         next = curr->next;
218         free(curr);
219         curr = next;
220     }
221 
222     free(list);
223 }

根据valgrind的说法,我一直在失忆,我真的不知道是什么导致了这个问题。

在不深入了解程序的情况下(因为缺少运行场景(即缺少主功能((,

如果您查看removeStart功能:

void* removeStart(LinkedList* list)
{
LinkedListNode* curr = (LinkedListNode*)malloc(sizeof(LinkedListNode));  
void* ptr;
curr = list->head;
...

您可以看到您使用curr指针来分配内存(通过调用malloc(,

LinkedListNode* curr = (LinkedListNode*)malloc(sizeof(LinkedListNode));
然后将其设置为list->head(curr=list->head(,这意味着您将丢失对刚才分配的内存的引用。

我不知道你的程序中是否有更多的内存泄漏,但这次很明显。

我建议你先把这个改成LinkedListNode* curr = list->head再次运行valgrind,看看是否还有泄漏。

正如上面评论中提到的,您可以从valgrind获得完整的报告,包括导致内存泄漏的代码行号。要获得这样的完整报告,您需要使用调试信息编译源代码(向gcc添加-g标志(,然后使用选项--leak-check=full运行valgrind。valgrind报告现在将包含导致内存泄漏的代码处的行。

最新更新