Reputation: 115
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
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 byptr
to be deallocated, that is, made available for further allocation. Ifptr
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,
free()
, it is perfectly legal to call free()
on the pointer returned by malloc()
and family of functions.Upvotes: 1
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