Valgrind: Invalid Read of Size 8 when freeing a linked list in C

926 Views Asked by At

I'm trying to free a linked list which is made up a list struct and multiple node stucts. Each node struct has a string attached to it.

My thought process is that if I start at the head and cycle through to the tail of a given list, and I free the string in each node and then the node. After every string and node is freed, then I free the list itself.

I need to free the string as I am mallocing the size of the string in another function earlier in my program.

My function is:

void releaseTB (TB tb){
    if(tb != NULL){
        if(tb->head != NULL){
            Node curr = tb->head;
            Node prev = NULL;
            while(curr != NULL && curr != tb->tail->next){
                prev = curr;
                curr = curr->next;
                free(prev->line);
                free(prev);
            }
        }
        free(tb);
    }
}

The condition curr != tb->tail->next in the while loop is dealing when I only want to free a sublist with in a greater list.

In case it is off relevance at all, these are my structs:

typedef struct textbuffer *TB;

typedef struct node *Node;

struct textbuffer{
    Node head;
    Node tail;
};

struct node{
    Node prev;
    Node next;
    char *line;
};

I get the correct output when running my program, but I am getting an Invalid read of size 8. The valgrind output is:

==7705== Memcheck, a memory error detector
==7705== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==7705== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==7705== Command: ./dry5
==7705== 
Original Tb:
1.1 abc
1.2 def
xxxxx

==7705== Invalid read of size 8
==7705==    at 0x400ADC: releaseTB (textbuffer.c:124)
==7705==    by 0x4013EF: deleteTB (textbuffer.c:355)
==7705==    by 0x4007FA: main (dry5.c:14)
==7705==  Address 0x51e0208 is 8 bytes inside a block of size 32 free'd
==7705==    at 0x4C29E90: free (vg_replace_malloc.c:473)
==7705==    by 0x400ACC: releaseTB (textbuffer.c:128)
==7705==    by 0x4013EF: deleteTB (textbuffer.c:355)
==7705==    by 0x4007FA: main (dry5.c:14)
==7705== 
First and second line are deleted...
xxxxx

Released Tb 
==7705== 
==7705== HEAP SUMMARY:
==7705==     in use at exit: 0 bytes in 0 blocks
==7705==   total heap usage: 11 allocs, 11 frees, 219 bytes allocated
==7705== 
==7705== All heap blocks were freed -- no leaks are possible
==7705== 
==7705== For counts of detected and suppressed errors, rerun with: -v
==7705== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

where: releaseTB (textbuffer.c:124) is while(curr != NULL && curr != tb->tail->next){ and 0x400ACC: releaseTB (textbuffer.c:128) is free(prev);.

Any help would be greatly appreciated. If any further clarification is needed, I'll do my best to explain it.

1

There are 1 best solutions below

5
On

Where is tb->tail pointing before you start the loop?

If it is NULL, tb->tail->next is wrong.

If it is not NULL, and is pointing to a node in the list, it is still wrong by the time you freed all the nodes.