C内存泄漏与valgrind

Cis*_*Bae 1 c valgrind pointers memory-leaks

我正在尝试在开源项目中使用C中的链表实现队列.我已经实现了Queue,编写了单元测试,并使用valgrind解决了大部分内存泄漏问题.

现在的问题是,我一直试图找到这几个小时的最后8个字节的泄漏,我似乎无法弄明白.

这是valgrind的输出:

==25806== 8 bytes in 1 blocks are definitely lost in loss record 1 of 1
==25806==    at 0x402BE68: malloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==25806==    by 0x80484E3: node_create (in /home/karysto/c-datastructures/queue/tests.out)
==25806==    by 0x8048511: enqueue (in /home/karysto/c-datastructures/queue/tests.out)
==25806==    by 0x8048851: test_dequeue_updates_size (in /home/karysto/c-datastructures/queue/tests.out)
==25806==    by 0x8048978: test_suite (in /home/karysto/c-datastructures/queue/tests.out)
==25806==    by 0x80489B0: main (in /home/karysto/c-datastructures/queue/tests.out)
==25806== 
==25806== LEAK SUMMARY:
==25806==    definitely lost: 8 bytes in 1 blocks
==25806==    indirectly lost: 0 bytes in 0 blocks
==25806==      possibly lost: 0 bytes in 0 blocks
==25806==    still reachable: 0 bytes in 0 blocks
==25806==         suppressed: 0 bytes in 0 blocks
==25806== 
Run Code Online (Sandbox Code Playgroud)

这是队列链表的结构:

struct Queue {
    int size;
    struct Node *front;
    struct Node *back;
};

struct Node {
    int data;
    struct Node *next;
};
Run Code Online (Sandbox Code Playgroud)

这是queue.c,实施dequeue.

void
dequeue(struct Queue *q) {

    /* Dequeue from an empty queue. */
    if (q->size == 0) {
        return;
    }

    /* Dequeue the only node. */
    else if (q->size == 1) {
        q->front = NULL;
        q->back  = NULL;
        free(q->front);
        free(q->back);
    }

    /* Regular case. */
    else if (q->size > 1) {
        struct Node *temp;
        temp = q->front;
        q->front = q->front->next;
        free(temp);
    }

    --(q->size);
    return;
}
Run Code Online (Sandbox Code Playgroud)

这是enqueue在同一个文件中.

void
enqueue(struct Queue *q, int data) {
    struct Node *head = node_create(data);

    /* First enqueue on empty. */
    if (q->front == NULL && q->back == NULL) {
        q->front = head;
        q->back  = head;
    }

    else {
        q->back->next = head;
        q->back       = head;
    }

    ++(q->size);
    return;
}
Run Code Online (Sandbox Code Playgroud)

对于completness,node_create这是从enqueue以下引用的函数:

struct Node*
node_create(int d) {
    struct Node *n = malloc(sizeof(struct Node));
    n->data = d;
    n->next = NULL;
    return n;
}
Run Code Online (Sandbox Code Playgroud)

M O*_*ehm 5

我认为你的问题在于将最后一个节点出列:

/* Dequeue the only node. */
else if (q->size == 1) {
    q->front = NULL;
    q->back  = NULL;
    free(q->front);
    free(q->back);
}
Run Code Online (Sandbox Code Playgroud)

你有效地打了free(NULL)两次.free(NULL)是允许的,但它没有做任何事情.所以你最终没有释放节点并丢失内存.您应该NULL在释放后分配到正面和背面,您还应该free只有最后一个节点一次:

/* Dequeue the only node. */
else if (q->size == 1) {
    free(q->front);
    q->front = NULL;
    q->back  = NULL;
}
Run Code Online (Sandbox Code Playgroud)

(这里,正面和背面都是相同的.当你出队时,你最多只能重新移动一个节点,所以你最多只能释放一个节点.)