Double free in C implementation of Queue

114 Views Asked by At

Here is my implementation of a Queue class in c, the struct queue_object* contains a void* object and a queue_object* next. Adding char 'A' and 'B' seems to work out, polling once too, but at the second poll I get:

free(): double free detected in tchache 2

I really dont get why I should be freeing one adress twice, please help!!

int queue_add(void* new_object, queue_object* queue) {
    if (new_object == NULL) {
        return 1;
    } else if (queue == NULL) {
        return 1;
    } else if (queue->object == NULL) {
        queue->object = new_object;
        return 0;
    }

    queue_object* newelement = (queue_object*) malloc(sizeof(queue_object));
    if (newelement == NULL) {
        return 1;
    }

    newelement->object = new_object;
    newelement->next = NULL;

    queue_object* tmp = queue;
    while (tmp->next != NULL) {
        tmp = tmp->next;
    }

    tmp->next = newelement;
    return 0;
}


void* queue_poll(queue_object* queue) {
    if (queue == NULL) {
        return NULL;
    }
    if (queue != NULL && queue->next == NULL) {
        void* data = queue->object;
        free(queue);
        return data;
    }
    void* data = queue->object;
    queue_object* tmp = queue;
    queue = queue->next;
    free(tmp);  // Entferne die Speicherfreigabe für tmp
    return data;
}

queue_object* new_queue(){
    // TODO
    queue_object* q = (queue_object*) malloc(sizeof(queue_object));
    if (q==NULL){
        return NULL;
    }
    q->next = NULL;
    q->object = NULL;
    return q;
}


void free_queue(queue_object* queue){
    // TODO
    if(queue == NULL){
        return;
    }
    else{
        queue_object* tmp0 = NULL;
        while (queue != NULL){
            tmp0 = queue;
            queue = queue->next;
            free(tmp0);
        }
    }
}

void* queue_peek(queue_object* queue){
    // TODO
    if(queue == NULL || queue->object == NULL){
        return NULL;
    }
    return queue->object;
}
1

There are 1 best solutions below

14
yvs2014 On

no to going into details there are quick minimal fixes in queue_add(), queue_poll(), free_queue()
note: call them properly, for example queue_poll(&queue)

queue_add

-int queue_add(void* new_object, queue_object* queue) {
+int queue_add(void* new_object, queue_object** q) {
+    queue_object* queue = *q;
     if (new_object == NULL) {
         return 1;
     } else if (queue == NULL) {

queue_poll

-void* queue_poll(queue_object* queue) {
+void* queue_poll(queue_object** q) {
+    queue_object* queue = *q;
     if (queue == NULL) {
         return NULL;
     }
     if (queue != NULL && queue->next == NULL) {
         void* data = queue->object;
         free(queue);
+         *q = NULL;
         return data;
     }
     void* data = queue->object;
-    queue_object* tmp = queue;
-    queue = queue->next;
-    free(tmp);  // Entferne die Speicherfreigabe für tmp
+    *q = queue->next;
+    free(queue);  // Entferne die Speicherfreigabe für tmp
     return data;
 }

free_queue

-void free_queue(queue_object* queue){
+void free_queue(queue_object** q){
+    queue_object* queue = *q;
     // TODO
     if(queue == NULL){
         return;
     }
     else{
-        queue_object* tmp0 = NULL;
         while (queue != NULL){
-            tmp0 = queue;
-            queue = queue->next;
-            free(tmp0);
+            *q = queue->next;
+            free(queue);
+            queue = *q;
         }
     }
 }