On 16/12/24 at 17:50, Greg Wooledge wrote:
On Mon, Dec 16, 2024 at 17:34:36 +0100, Franco Martelli wrote:
void dealloc()
{
        for ( const DIGIT *p = head; p->next != NULL; p = p->next )
                if ( p->prev != NULL )
                        free( p->prev );
        free( last );
}

I think you might have an off-by-one error in this function.  You stop
the for loop when p->next == NULL, which means you never enter the body
during the time when p == last.  Which means you never free the
second-to-last element in the list.

It is p->prev not p->next, by doing so free() don't apply for the "last"
element so I've to free apart


Given a list of 5 items, you will free items 1, 2, 3 (during the loop)
and 5 (after the loop), but not 4.

OK I'll try some test removing the "if statement"

No, it's not the if statement.  It's the for loop's iteration condition.

        for ( const DIGIT *p = head; p->next != NULL; p = p->next )

Your iteration condition is  p->next != NULL  so  you stop iterating as
soon as p->next == NULL.

Given this linked list:

   NULL <- [1] <-> [2] <-> [3] <-> [4] <-> [5] -> NULL
            ^                               ^
            head                            last

Your first loop iteration, when p == head, does nothing because of
the if statement.  That's fine.

The second iteration, when p points to [2], frees [1].

The third iteration, when p points to [3], frees [2].

The fourth iteration, when p points to [4], frees [3].

The fifth iteration, when p points to [5], NEVER HAPPENS, because
p->next == NULL at that point, and the for loop stops.  So [4] is
not freed.

After the loop, you free [5] which is where last points.

You're correct! To verify I've added "free( last->prev );" to dealloc():

void dealloc()
{
        for ( const DIGIT *p = head; p->next != NULL; p = p->next )
                if ( p->prev != NULL )
                        free( p->prev );
        free( last->prev );
        free( last );
}

and it worked, now the output of Valgrind is:

$ valgrind --track-origins=yes --leak-check=full -s ./a.out
==114549== Memcheck, a memory error detector
==114549== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
==114549== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
==114549== Command: ./a.out
==114549==
12345678
==114549==
==114549== HEAP SUMMARY:
==114549==     in use at exit: 0 bytes in 0 blocks
==114549==   total heap usage: 9 allocs, 9 frees, 1,216 bytes allocated
==114549==
==114549== All heap blocks were freed -- no leaks are possible
==114549==
==114549== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

I'll change the "for condition" thanks very much again

--
Franco Martelli

Reply via email to