简体   繁体   English

C valgrind发生内存泄漏

[英]C Memory leak with valgrind

I'm trying to implement a Queue using a linked list in C, in an open-source project. 我正在尝试在一个开源项目中使用C中的链接列表来实现Queue。 I'm at the point where I've implemented the Queue, wrote unit tests, and worked out most of the memory leaks using valgrind. 我已经实现了Queue,编写了单元测试,并使用valgrind解决了大部分内存泄漏。

The problem now is that I've been trying to find the leak for these last 8 bytes for a couple hours now, and I can't seem to figure it out. 现在的问题是,我已经尝试了几个小时来查找最后8个字节的泄漏,但似乎无法弄清楚。

Here is the output from valgrind: 这是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== 

Here's my structs for the queue linked list: 这是队列链接列表的结构:

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

struct Node {
    int data;
    struct Node *next;
};

Here's queue.c , the implementation for dequeue . 这是queue.cdequeue的实现。

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;
}

And here's the enqueue in the same file. 这是同一个文件中的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;
}

For completness, here's the node_create function that is being referenced from enqueue : 为了完整起见, node_create是从enqueue引用的node_create函数:

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

I think that your problem lies in dequeuing the last node: 我认为您的问题出在最后一个节点的出队上:

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

You effectively call free(NULL) twice. 您有效地调用了两次free(NULL) free(NULL) is allowed, but it doesn't do anything. 允许使用free(NULL) ,但不执行任何操作。 So you end up not freeing the node and lose the memory. 因此,您最终将无法释放节点并丢失内存。 You should assign NULL to the front and back after freeing and you should also free the last node only once: 您应该分配NULL释放后的正面和背面,你也应该free的最后一个节点只有一次:

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

(Here, the front and back are the same. You are also remobving at most one node when dequeuing, so you should only free at most one node.) (这里,前后是相同的。出队时,您最多也要删除一个节点,因此您最多只能释放一个节点。)

How about: 怎么样:

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

Explanation: In your original solution you were first pointing both q->front and q->back to NULL before free() ing them. 说明:在原始解决方案中,您首先要在free()之前将q->frontq->back指向NULL Running free() on NULL doesn't destroy the universe but it doesn't do very much, ie not free() ing your last node. NULL 运行free() 不会破坏Universe,但是它并不能做很多事情,即不对您的最后一个节点进行free()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM