正确的释放记忆的方法

时间:2014-01-04 16:27:45

标签: c memory-leaks

我使用优先级队列创建程序,我需要在程序结束时释放所有内存。我使用Valgrind来查找内存泄漏,我在此代码中收到警告:

int len;

//vlozeni prvniho prvku
len = snprintf(NULL, 0, "%d,%d", startX, startY);
char *link = malloc(len + 1);
sprintf(link,"%d,%d", startX, startY);
priq_push(queue, link, 0);

while(1)
{
    for(some_condition)
    {
        if(another_condition)
        {
            len = snprintf(NULL, 0, "%d,%d", neighbourX, neighbourY);
            link = realloc(NULL, len + 1);
            sprintf(link,"%d,%d", neighbourX, neighbourY);
            priq_push(queue, link, elementHeight + heights[neighbourX][neighbourY]);
            break;
        }
    }

    if(f == 1)
    {
        break;
    }
}

free(link);

使用此代码,我从Valgrind得到这个警告:

4 bytes in 1 blocks are definitely lost in loss record 1 of 4
==9069==    at 0x4C2C857: malloc (vg_replace_malloc.c:291)
==9069==    by 0x401233: main (main.c:229)
==9069== 
==9069== 7,628,843 bytes in 932,764 blocks are definitely lost in loss record 4 of 4
==9069==    at 0x4C2C857: malloc (vg_replace_malloc.c:291)
==9069==    by 0x4C2C9CB: realloc (vg_replace_malloc.c:687)
==9069==    by 0x401554: main (main.c:305)

第291行是第一个malloc:char *link = malloc(len + 1);

我做错了什么?

修改。

void priq_push(priority_queue q, void *data, int height)
{
    q_elem_t *b;
    int n, m;

    if (q->position >= q->alloc) 
    {
        q->alloc *= 2;
        b = q->buffer = realloc(q->buffer, sizeof(q_elem_t) * q->alloc);
    } 
    else
    {
        b = q->buffer;
    }

    n = q->position++;
    /* append at end, then up heap */
    while ((m = n / 2) && height < b[m].height)
    {
        b[n] = b[m];
        n = m;
    }
    b[n].data = data;
    b[n].height = height;
}

/* remove top item. returns 0 if empty. *priority can be null. */
void * priq_pop(priority_queue q, int *height)
{
    void *out;
    if (q->position == 1)
    {
        return 0;
    }

    q_elem_t *b = q->buffer;

    out = b[1].data;
    if (height)
    {
        *height = b[1].height;
    }

    /* pull last item to top, then down heap. */
    --q->position;

    int n = 1, m;
    while ((m = n * 2) < q->position) 
    {
        if (m + 1 < q->position && b[m].height > b[m + 1].height)
        {
            m++;
        }

        if (b[q->position].height <= b[m].height)
        {
            break;
        }
        b[n] = b[m];
        n = m;
    }

    b[n] = b[q->position];
    if (q->position < q->alloc / 2 && q->position >= 16)
    q->buffer = realloc(q->buffer, (q->alloc /= 2) * sizeof(b[0]));

    return out;
}

我自己编写函数,它将在最后释放队列

void free_queue(priority_queue queue)
{
    free(queue->buffer);
    free(queue);
}

2 个答案:

答案 0 :(得分:2)

优先级队列保留您传递它的指针。这意味着队列必须承担内存的所有权。您需要从队列中提取项目的代码,以便在处理每个项目时调用free

我们无法看到代码,它是实际调用priq_pop的代码。但泄漏报告似乎表明调用priq_pop的代码不会释放返回的项目。

您解决此问题的步骤是:

  1. realloc替换为等效的malloc,但读起来更好。
  2. 删除推送循环结束时的free(link)。这是不正确的,因为队列拥有内存。
  3. 每当您致电free()并完成处理退回的项目时,都会向priq_pop添加来电。

答案 1 :(得分:0)

您最终应该释放队列中推送的所有链接。