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