The other answers here point to the main problem - because you are looking for your apple, when you call destroyEntry in main (), it passes by reference, creating a copy.
Even when you know your problem, it helps to return to the error and try to connect the text of what you see to the problem, so the next time it appears, you are likely to quickly. I find that C and C ++ errors sometimes seem insanely ambiguous.
As a rule, when I have problems with freeing pointers or deleting objects, I like typing addresses, especially when I select them and when I try to free them. valgrind already gave you the address of a bad pointer, but helps to compare it with a good one.
int main() { Entry * apple; apple = malloc(sizeof(Entry)); printf("apple address = %p", apple);
After that, you will notice that the printf () operator gave you an address similar to 0x8024712 (just making up the address in the right general range), but your output valgrind gave 0x4028E58. You would notice that they are in two different places (in fact, "0x4 ..." is on the stack, not the heap from which malloc () is allocated, but I assume that you are just starting and not the red flag for you) , so you know that you are trying to free memory due to the wrong place, therefore, "invalid free ()".
So, from there you can say to yourself: "Okay, somehow my pointer is getting corrupted." You have already blamed your problem on a small, compiled example, so you donβt need much time to solve this problem.
TL; DR - when working with errors related to pointers, try printing addresses or finding them in your favorite debugger. This often at least points you in the right direction.
None of this should prevent you from posting your question to Stack Exchange, of course. Hundreds of programmers are likely to benefit from doing this.