I have built a function to insert a node into a doubly-linked list. The structure includes 2 strings, for which I am dynamically allocating space inside the function. According to Valgrind, this causes a memory leak. Here is a simplified version of my code:
typedef struct Node {
char *str1, *str2;
Node *next, *prev;
};
void add(Node* list, char* string1, char* string2) {
Node* temp = list;
Node* new_node = (Node*) malloc(sizeof(Node));
if (!new_node) return;
new_node->str1 = (char*) malloc(30*sizeof(char));
new_node->str2 = (char*) malloc(30*sizeof(char));
strcpy(new_player->str1, string1);
strcpy(new_player->str2, string2);
if (!temp) {
temp = new_node;
new_node->prev = new_node->next = NULL;
new_node = NULL;
free(new_node);
return;
} else {
while (temp->next) temp = temp->next;
new_node->prev = temp;
new_node->next = NULL;
temp->next =new_node;
new_node = NULL;
free(new_node);
}
void destroy(Node* list) {
Node* temp;
while (list) {
temp = list->next;
free(list->str1);
free(list->str2);
free(list);
list = temp;
}
}
I am using the destroy function inside of main() after having finished working with the list. Is that not enough? Am I supposed to somehow free the strings inside the add function?
I am using this function repeatedly in my program so it causes a loss of around 10.0000 bytes. Can you please tell me why this memory leak occurs and how can I get rid of it?
Your add
function malloc
sa Node
, links it into the list and then free
s the allocated Node
for some reason. That will leave dangling pointers in the list.
Your add
function also has no mechanism to add the first Node
to an empty list. There are two ways that you could do that. The first way is to return a pointer to the first node of the list:
Node* add(Node* list, char* string1, char* string2) {
Node* temp = list;
Node* new_node = malloc(sizeof(Node));
if (!new_node) return NULL;
new_node->str1 = malloc(strlen(string1)+1);
new_node->str2 = malloc(strlen(string2)+1);
if (!new_node->str1 || !new_node->str2) {
// allocation error for one of the strings
free(new_node->str1);
free(new_node->str2);
free(new_node);
return NULL;
}
strcpy(new_node->str1, string1);
strcpy(new_node->str2, string2);
new_node->next = NULL;
if (!temp) {
new_node->prev = NULL;
list = new_node;
} else {
while (temp->next) temp = temp->next;
new_node->prev = temp;
temp->next = new_node;
}
// return pointer to first node
return list;
}
Example call using the first way:
Node* mylist = NULL;
...
mylist = add(mylist, "hello", "world");
The second way is to change the first parameter to a pointer to a pointer to the start of the list:
void add(Node** list, char* string1, char* string2) {
Node* temp = *list;
Node* new_node = malloc(sizeof(Node));
if (!new_node) return;
new_node->str1 = malloc(strlen(string1)+1);
new_node->str2 = malloc(strlen(string2)+1);
if (!new_node->str1 || !new_node->str2) {
// allocation error for one of the strings
free(new_node->str1);
free(new_node->str2);
free(new_node);
return;
}
strcpy(new_node->str1, string1);
strcpy(new_node->str2, string2);
new_node->next = NULL;
if (!temp) {
new_node->prev = NULL;
*list = new_node;
} else {
while (temp->next) temp = temp->next;
new_node->prev = temp;
temp->next = new_node;
}
}
Example call using the second way:
Node* mylist = NULL;
...
add(&mylist, "hello", "world");
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.