cmemory-leaksfree

Definitely lost memory even though I free in C


I want to create a function that, when given a struct with a pointer in it to another struct of the same type, it finds all of the pointers and frees them.
The struct would be:

typedef struct example_ {
    uint16_t something;
    bool blabla;
    struct example_ *further_in; 
} example;

And the function I have created to free every pointer is:

bool free_examples(example p) {
    bool isCounting = true;
    int16_t count = 0;
    example firstexample = p;
    while (isCounting) // counts how many examples there are
    {
        if (p.further_in == NULL)
        {
            isCounting = false; 
        }
        else if (p.further_in != NULL)
        {
            count++;
            p = *(p.further_in);
        }       
    }
    p = firstexample;
    example *n = malloc(sizeof(example));
    for (int i = 0; i < count; i++) // frees every pointer?
    {
        n = p.further_in;
        free(p.further_in);
        p = *(n);
    }
    free(n);    
    return true;
}

First of all, I'm new to programming and C so I don't even know if my code does what I want it to do.
Secondly, my problem is that when I run this through valgrind, it returns that 16 bytes are definitely lost at this line:

example *n = malloc(sizeof(example));

As you can see I free "n", later. I don't understand how it's still leaked.

Thanks in advance for any help!


Solution

  • This code snippet:

    p = firstexample;
    example *n = malloc(sizeof(example));
    for (int i = 0; i < count; i++) // frees every pointer?
    {
        n = p.further_in;
        free(p.further_in);
        p = *(n);
    }
    free(n); 
    

    at least produces a memory leak and moreover has undefined behavior.

    In this line:

    example *n = malloc(sizeof(example));
    

    there is allocated memory and its address is assigned to the pointer n. and then in the following for loop the pointer n was reassigned:

        n = p.further_in;
    

    So the address of the allocated memory is lost.

    Also this statement

    p = *(n);
    

    accesses memory that was already freed that results in undefined behavior.

    Also it is unclear whether the passed object of the type example:

    bool free_examples(example p) {
                              ^^^
    

    is stored in a dynamically allocated memory or not. If it is indeed is placed in a dynamically allocated memory then it also should be freed and the function should be declared at least like:

    void free_examples(example *p) {
                               ^^^
    

    The return type bool also does not make sense.

    Pay attention to that counting the number of non null pointers does not make sense relative to the process of freeing allocated memory and is inefficient and redundant.

    If you have a singly-linked list where all nodes of the list are allocated dynamically then the function can look the following way:

    void free_examples( example **p ) 
    {
        while ( *p != NULL )
        {
            example *current = *p;
            *p = ( *p )->further_in;
            free( current );
        }
    }
    

    And if in the caller you have a pointer to the first node of the list that was allocated dynamically like for example:

    example *head = malloc( sizeof( example ) );
    

    then the function is called like:

    free_examples( &head );