奇怪的双重自由行为

时间:2015-11-26 18:28:42

标签: c pointers malloc free double-free

下面我有一个函数trim()。从一组int中删除前导零。它返回一个指针,它从malloc()接收。在运行对trim()free()的连续调用循环时。我注意到trim()返回的值(由malloc()收到)在每次迭代时都是相同的。

我理解释放两次相同的指针,如果它不是NULL,将导致双重释放错误。为什么在这种情况下没有遇到双重免费错误?

#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

2 个答案:

答案 0 :(得分:2)

你所看到的不是双重免费。考虑:

void *p1, *p2;

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

此时无法保证p1和p2相同。不能保证他们不同。如果它们碰巧是相同的,那么此时调用free(p2) 是免费的。以下是实际的双重免费:

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

答案 1 :(得分:1)

据我所知,你的案例中没有 double free()

首先,使用malloc()分配内存,然后使用free()分配内存。在存储块空闲d之后,可以使用下一次调用malloc()重新分配它(即,可以返回相同的指针)。这也是完全合法的(也是必需的)。

如果我们仔细研究C11规范,章节§7.22.3.3,它会说(强调我的

  

free函数会导致ptr指向的空格被释放,即制作   可用于进一步分配。如果ptr是空指针,则不执行任何操作。否则,如果   参数与先前由内存管理返回的指针不匹配   函数,或者如果通过调用free或realloc释放空间,则   行为未定义。

所以,

  1. 一旦释放,就可以重新分配一个内存空间(指向一个指针)。
  2. 除非之前通过调用free()释放指针 ,否则在free()和家人返回的指针上调用malloc()是完全合法的功能。