奇怪的双重自由行为
Strange double free behavior
下面我有一个函数trim()
。从整数数组中删除前导零。它 returns 一个指针,它从 malloc()
接收。而 运行 连续调用 trim()
和 free()
的循环。我注意到 trim()
返回的值 - malloc()
接收到的值在每次迭代中都是相同的。
据我了解,释放同一个指针两次,如果不是NULL
,将导致双重释放 错误。为什么在这种情况下没有遇到 double free 错误?
#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;
}
输出:
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
您看到的不是双重免费。考虑:
void *p1, *p2;
p1 = malloc(10);
free(p1);
p2 = malloc(10);
目前无法保证 p1 和 p2 相同。不能保证它们是不同的。如果碰巧相同,此时调用free(p2)
是不是双倍免费。以下将是实际的双重免费:
void *p = malloc(10);
free(p);
free(p);
据我所知,您的情况没有 double free()。
首先,您使用 malloc()
分配内存,然后 free()
它。内存块被释放后,可以使用下一次调用 malloc()
重新分配它(即,可以返回相同的指针)。释放它也是完全合法的(也是必需的)。
如果我们仔细查看 C11
规范,第 7.22.3.3 章,它说(强调我的)
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.
所以,
- 释放后,可以重新分配内存space(指向您的指针)。
- 除非指针只是之前被调用
free()
释放,否则在[=返回的指针上调用free()
是完全合法的10=] 和函数族。
下面我有一个函数trim()
。从整数数组中删除前导零。它 returns 一个指针,它从 malloc()
接收。而 运行 连续调用 trim()
和 free()
的循环。我注意到 trim()
返回的值 - malloc()
接收到的值在每次迭代中都是相同的。
据我了解,释放同一个指针两次,如果不是NULL
,将导致双重释放 错误。为什么在这种情况下没有遇到 double free 错误?
#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;
}
输出:
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
您看到的不是双重免费。考虑:
void *p1, *p2;
p1 = malloc(10);
free(p1);
p2 = malloc(10);
目前无法保证 p1 和 p2 相同。不能保证它们是不同的。如果碰巧相同,此时调用free(p2)
是不是双倍免费。以下将是实际的双重免费:
void *p = malloc(10);
free(p);
free(p);
据我所知,您的情况没有 double free()。
首先,您使用 malloc()
分配内存,然后 free()
它。内存块被释放后,可以使用下一次调用 malloc()
重新分配它(即,可以返回相同的指针)。释放它也是完全合法的(也是必需的)。
如果我们仔细查看 C11
规范,第 7.22.3.3 章,它说(强调我的)
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.
所以,
- 释放后,可以重新分配内存space(指向您的指针)。
- 除非指针只是之前被调用
free()
释放,否则在[=返回的指针上调用free()
是完全合法的10=] 和函数族。