Reputation: 154
I'm trying to identify the reason why Valgrind is complaining.
If somebody could give me a hint so that I can understand why my code is generating bad behaviour I would be very grateful.
I've created an array of structures. Each entry is the beginning of a linked list made out of structs. Now I'm at the Point where I want to free the elements of each linked list of that array of structs.
But Valgrind is saying:
==15084== Memcheck, a memory error detector
==15084== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==15084== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==15084== Command: /tmp/3RKi4ZeFa74f-a.out tests/16_allPositive output/ausgabe_16_allPositive
==15084==
==15084== Invalid read of size 8
==15084== at 0x402006: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0de8 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FEA: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084== Invalid read of size 8
==15084== at 0x401FFA: reset (1441261801.c:807)
==15084== by 0x402489: main (1441261801.c:927)
==15084== Address 0x51e0d48 is 8 bytes inside a block of size 16 free'd
==15084== at 0x4C29E90: free (vg_replace_malloc.c:473)
==15084== by 0x401FF5: reset (1441261801.c:809)
==15084== by 0x402489: main (1441261801.c:927)
==15084==
==15084==
==15084== HEAP SUMMARY:
==15084== in use at exit: 0 bytes in 0 blocks
==15084== total heap usage: 119 allocs, 119 frees, 7,787 bytes allocated
==15084==
==15084== All heap blocks were freed -- no leaks are possible
==15084==
==15084== For counts of detected and suppressed errors, rerun with: -v
==15084== ERROR SUMMARY: 51 errors from 3 contexts (suppressed: 0 from 0)
That seems to be the faulty function
void reset()
784: {
785: //lösche alle (zeiger)char *arrays der conti structs
786: for(int i = 0; i < zeile1; i++)
787: {
788: struct node *p = &conti[i];
789: if((*p).next != NULL)
790: {
791: for(; (*p).next != NULL; p=(*p).next)
792: {
793: free((*p).volume);
794: }
795: free((*p).volume);
796: }else if ((*p).next == NULL)
797: {
798: free((*p).volume);
799: }
800: }
801: //lösche die listenelemente der jeweiligen container
802: for(int i = 0; i < zeile1; i++)
803: {
804: struct node *p = &conti[i];
805: if((*p).next != NULL)
806: {
807: for(; (*p).next != NULL; p=(*p).next)
808: {
809: free((*p).next);
810: }
811: }
812: }
813: //lösche die (zeiger)input char *arrays
814: for (int j = 0; j < zeile2; j++)
815: {
816: free(input[j].volume);
817: }
818: //lösche die struct arrays
819: free(conti);
820: free(input);
821: }
The structures look like this:
16: struct node {
17: char *volume;
18: struct node *next;
19: };
I'm looking forward for your help.
Upvotes: 2
Views: 5171
Reputation: 754560
Note that Tom Tanner gave the correct diagnosis in his answer. Please give him the credit for that.
Please use the ->
arrow operator instead of (*p).next
; it was invented for a good reason.
Your freeing code is currently:
struct node *p = &conti[i];
if((*p).next != NULL)
{
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
}
Note that the loop repeats the test made in the if
condition in your code; that's unnecessary and you can simply remove the if
code, but not the loop inside it, of course.
The code should take care to avoid accessing freed memory. You can do that with a more or less standard technique which preserves the next
pointer value before the memory is free:
struct node *p = &conti[i]->next;
while (p != NULL)
{
struct node *next = p->next;
free(p);
p = next;
}
Upvotes: 2
Reputation: 9354
This is a fairly typical coding style which works until (a) you use valgrind or (b) actually have a system where another thread can get hold of your memory when you've freed it.
for(; (*p).next != NULL; p=(*p).next)
{
free((*p).next);
}
As you go through that loop, you get hold of p and then you free the thing it is pointing to.
free(p->next); //p->next now points to freed memory
Then you get hold of the thing you've just freed
p = p->next; //p now points to freed memory
and then you tree to free what that is pointing to
free(p->next); //Trying to access freed memory
Then you have to have extra code to free the first element in the list because you can't have freed it in that loop.
Upvotes: 2