Quantcast
Channel: Programming Forums
Viewing all articles
Browse latest Browse all 51036

memory leak when trying to merge two linked lists

$
0
0
I have a memory leak when I try to merge two linked lists in another one. I tried to use list_destroy(&merge) however the memory was already gone by the time I did that. Thus, I don't know what to do.

 

#ifndef LIST_H
#define	LIST_H

#include <stdlib.h>

// define a structure for a node 
typedef struct ListElmt_ {
    
  void* data; 
  struct ListElmt_* next;

} ListElmt;

// define a structure for a list 
typedef struct List_ {
    
  int size; 
  ListElmt* head; 
  ListElmt* tail; 
  void (*destroy)(void* data);  
} List;

// public interface

void list_init(List *list, void (*destroy)(void *data));
void list_destroy(List *list);
int list_ins_next(List *list, ListElmt *element, const void *data);
int list_rem_next(List *list, ListElmt *element, void **data);
int list_concat(List* merge, List* list1, List* list2);

// macros

#define list_size(list) ((list)->size)
#define list_head(list) ((list)->head)
#define list_tail(list) ((list)->tail)
#define list_data(element) ((element)->data)
#define list_next(element) ((element)->next)
#define list_is_tail(element) ((element)->next == NULL ? 1 : 0)
#define list_is_head(element) ((element) == (list)->head ? 1 : 0)

#endif	/* LIST_H */



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

/* initialize all the list data */
void list_init(List* list, void (*destroy)(void* data)) {

    list->size = 0;
    list->destroy = destroy;
    list->head = NULL;
    list->tail = NULL;
}

// attempt to insert a new node into the list 
int list_ins_next(List* list, ListElmt* element, const void* data) {

    ListElmt* new_element;
    if((new_element = malloc(sizeof(ListElmt))) == NULL)
        return -1;  
    /* insert new data inside a new element */
    new_element->data = (void*) data;
    /* insert the new element at the head of the list */
    if (element == NULL) {
        if (list_size(list) == 0)
            list->tail = new_element;

        new_element->next = list->head;
        list->head = new_element;
    }
    /* insert new element at another place other than the head */
    else {

        if (element->next == NULL)
            list->tail = new_element;

        new_element->next = element->next;
        element->next = new_element;
    }
    /* update the list size */
    list->size++;
    return 0;
}

// attempt to remove a node of the list
int list_rem_next(List *list, ListElmt *element, void **data) {

    ListElmt* old_element;
    /* verify if the list is already empty */
    if (list_size(list) == 0)
        return -1;
    /* remove from the head of the list */
    if (element == NULL) {
        /* keep data and reference of the head to be removed */
        *data = list->head->data;
        old_element = list->head;
        /* remove the head of the list */
        list->head = list->head->next;
        /* verify if there is only one node */
        if (list_size(list) == 1)
            list->tail = NULL;
    }/* remove from somewhere other than the head */
    else {
        /* verify if there is a node to be removed */
        if (element->next == NULL)
            return -1;
        /* keep data and reference of the element to be removed*/
        *data = element->next->data;
        old_element = element->next;
        /* remove the element from the list */
        element->next = element->next->next;
        /* verify if the element is the last one */
        if (element->next == NULL)
            list->tail = element;
    }
    /* free old element's memory*/
    free(old_element);
    /* adjust the size of the list */
    list->size--;
    return 0;
}

// remove all nodes of the list
void list_destroy(List* list) {

    void* data;
    /* remove each element until there are no more elements*/
    while (list_size(list) > 0) {
        /* deallocate memory from data */
        if (list_rem_next(list, NULL, (void**) &data) == 0 && list->destroy != NULL) {
            list->destroy(data);
        }
    }
    /* make sure there's no more allocated data */
    memset(list, 0, sizeof (List));
}

int list_concat(List* merge, List* list1, List* list2)
{
    ListElmt* element; 
    // insert each element of the first list into the merge list 
    for(element = list_head(list1); element != NULL; element = list_next(element))
    {
       if(list_ins_next(merge, NULL, list_data(element)) != 0)
         return -1;  
    }
    // insert each element of the second list into the merge list 
    for(element = list_head(list2); element != NULL; element = list_next(element))
    {
       if(list_ins_next(merge, list_tail(merge), list_data(element)) != 0)
         return -1;  
    }
    return 0;    
}



#include <stdio.h>
#include <stdlib.h>

#include "list.h"

static void print_list(List* list) {
    ListElmt* element;
    int* data;
    int i = 0;
    /* display the size of the list */
    fprintf(stdout, "List size is %d\n", list_size(list));
    /* display each data of the elements of the list */
    for (element = list_head(list); element != NULL; element = list_next(element)) {
        data = list_data(element);
        fprintf(stdout, "list[%03d] = %03d\n", i, *data);
        i++;
    }
}

int main(void) {

    List list1;
    List list2;
    List merge;
    int i;
    int* data;
    
    /* initialize the lists */
    list_init(&list1, free);
    list_init(&list2, free);
    list_init(&merge, free);
    
    /* insert numbers at the head of the list */
    for(i = 9; i >= 0; i--)
    {
       if((data = malloc(sizeof(int))) == NULL)
          return EXIT_FAILURE;
       *data = i; 
       if(list_ins_next(&list1, NULL, data) != 0)
          return EXIT_FAILURE; 
    }
    /* print the first list */
    print_list(&list1);
    
    for(i = 19; i >= 10; i--)
    {
       if((data = malloc(sizeof(int))) == NULL)
          return EXIT_FAILURE;
       *data = i; 
       if(list_ins_next(&list2, NULL, data) != 0)
          return EXIT_FAILURE; 
    }
    /* print the second list */
    print_list(&list2);
    
    list_concat(&merge, &list1, &list2);
    
    // print the merge list 
    print_list(&merge);
    
    // deallocate all the remaining memory of the lists
    list_destroy(&list1);
    list_destroy(&list2);
    
    return EXIT_SUCCESS;
}



==2936== HEAP SUMMARY:
==2936==     in use at exit: 320 bytes in 20 blocks
==2936==   total heap usage: 60 allocs, 40 frees, 720 bytes allocated
==2936== 
==2936== 320 (16 direct, 304 indirect) bytes in 1 blocks are definitely lost in loss record 3 of 3
==2936==    at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2936==    by 0x400869: list_ins_next (list.c:17)
==2936==    by 0x400AAB: list_concat (list.c:102)
==2936==    by 0x4007E1: main (listapp.c:56)
==2936== 
==2936== LEAK SUMMARY:
==2936==    definitely lost: 16 bytes in 1 blocks
==2936==    indirectly lost: 304 bytes in 19 blocks


Viewing all articles
Browse latest Browse all 51036

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>