hermetik
hermetik

Reputation: 115

Strange double free behavior

Below I have a function trim(). Which removes the leading zeros from an array of ints. It returns a pointer, which it receives from malloc(). While running a loop of successive calls to trim() and free(). I noticed that the value returned by trim() - which was received by malloc(), is identical on every iteration.

It is my understanding that freeing the same pointer twice, if it is not NULL, will result in a double free error. Why is a double free error not encountered in this situation?

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i, j, length;
    int n[] = { 4, 5, 6 };
    int m[] = { 0, 3, 5 };
    int *num;
    int *trimmed, *trimmed_length;

    trimmed_length = &length;

    for (i = 0; i < 10; i++)
    {
        num = (i % 2 == 0) ? n : m;

        trimmed = trim(num, 3, trimmed_length);

        if (!trimmed)
        {
            printf("trimmed was null\n");
            exit(-1);
        }

        for (j = 0; j < *trimmed_length; j++)
        {
            printf("%d", trimmed[j]);
        }   

        printf("\n");

        free(trimmed); 
    }

    exit(0);
}

int *trim(int *n, int nlength, int *res_length)
{
    int i, j;
    int *res;

    for (i = 0; i < nlength; i++)
    {
        if (n[i] > 0)
        {
            break;
        }
    }

    *res_length = (nlength - i);

    res = malloc(sizeof(int) * (*res_length));

    if (!res)
    {
        return NULL;
    }

    j = 0;

    while (i < nlength)
    {
        res[j++] = n[i++];
    }

    printf("Returned pointer from trim() %d\n", res);

    return res;
}

Output:

Returned pointer from trim() 11759632
456
Returned pointer from trim() 11759632
35
Returned pointer from trim() 11759632
456
Returned pointer from trim() 11759632
35
Returned pointer from trim() 11759632
456
Returned pointer from trim() 11759632
35
Returned pointer from trim() 11759632
456
Returned pointer from trim() 11759632
35
Returned pointer from trim() 11759632
456
Returned pointer from trim() 11759632
35

Upvotes: 1

Views: 225

Answers (2)

Sourav Ghosh
Sourav Ghosh

Reputation: 134286

As far as I can see, there is no double free() in your case.

First, you allocate the memory using malloc(), then you free() it. After a memory block has been free-d, it can be re-allocated (i.e, the same pointer can be returned) using a next call to malloc(). It is perfectly legal (and required) to free that, too.

If we look closely at the C11 spec, chapter §7.22.3.3, it says (emphasis mine)

The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.

So,

  1. Once freed, a memory space (pointed y a pointer) can be re-allocated.
  2. Unless the pointer is just previously freed by a call to free(), it is perfectly legal to call free() on the pointer returned by malloc() and family of functions.

Upvotes: 1

keithmo
keithmo

Reputation: 4943

What you're seeing is not a double free. Consider:

void *p1, *p2;

p1 = malloc(10);
free(p1);
p2 = malloc(10);

At this point there's no guarantee that p1 and p2 are the same. There's no guarantee they're different. If they happen to be the same, calling free(p2) at this point is not a double free. The following would be an actual double free:

void *p = malloc(10);
free(p);
free(p);

Upvotes: 2

Related Questions