我制作了自己的通用链表,但在我的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报告现在将包含导致内存泄漏的代码处的行。