2015-04-21 7 views
1

Я пытаюсь реализовать очередь с использованием связанного списка на C в проекте с открытым исходным кодом. Я нахожусь в точке, где я реализовал Queue, написал модульные тесты и разработал большую часть утечек памяти, используя valgrind.C Утечка памяти с 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== 

Вот мои для структур очереди связного списка:

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

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

Вот 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; 
} 

И вот 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; 
} 

Для Комплектность, вот node_create функция, на которую ссылается из enqueue:

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

'q-> front = NULL; свободный (q-> фронт) '- не должно быть наоборот? И не 'q-> front' и' q-> back' одинаковы в одноузловой очереди? –

+0

Вы правы в том, что 'q-> front = NULL' должен быть после, но если я их переключу, компиляция создаст' *** glibc обнаруженный *** ./tests.out: двойной свободный или коррупционный (fasttop) 'ошибка. – CisBae

+1

Да, это вторая логическая ошибка в вашем фрагменте. Вы можете освобождать один и тот же узел один раз, независимо от того, через какой указатель вы обращаетесь к нему. –

ответ

5

Я думаю, что ваша проблема заключается в извлечении из последнего узла:

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

Вы эффективно назвать free(NULL) дважды. free(NULL) разрешен, но он ничего не делает. Таким образом, вы не освобождаете узел и не теряете память. Вы должны назначить NULL на передней и задней части после освобождения и вы должны также free последний узел только один раз:

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

(Здесь, передняя и задняя одинаковы Вы также remobving более одного узла, когда извлечение из. , поэтому вы должны освобождать не более одного узла.)

+0

Большое спасибо @M Oehm! Ваше объяснение ясное, и он исправил утечку памяти. Я продолжу это. – CisBae

+0

'free (NULL)' не является причиной утечки памяти (это не-op), что может смутить читателей. Причина заключается в том, чтобы освободить выделенный узел. – Betamos

+0

@Betamos: 'free (NULL)' приводит к утечке памяти, потому что OP думал, что он освободил память, но не сделал этого. Я согласен с тем, что объяснение было путаным и переписало его. –

1

Как насчет:

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

Объяснение: В своем первоначальном решении вы были первым, указывая как q->front и q->back до NULL до free() их. Запуск free() на NULLdoesn't destroy the universe, но это не очень много, то есть не free() вашего последнего узла.

+0

Спасибо за решение @Betamos, он работает! Я выбрал ответ Оема для объяснения этого. – CisBae

Смежные вопросы