2014-11-30 2 views
0
#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 

struct strqueue { 
    struct lnode *front; 
    struct lnode *back; 
    int length; 
}; 

struct lnode { 
    char *item; 
    struct lnode *next; 
}; 

StrQueue create_StrQueue(void) { 
    struct strqueue *sq = malloc(sizeof(struct strqueue)); 
    sq->length = 0; 
    sq->front = NULL; 
    sq->back = NULL; 
    return sq; 
} 

void destroy_nodes(struct lnode *l) { 
    while (l!=NULL) { 
     struct lnode *c = l; 
     l=l->next; 
     free(c); 
    } 
} 

void destroy_StrQueue(StrQueue sq) { 
    destroy_nodes(sq->front); 
    free(sq); 
} 

void sq_add_back(StrQueue sq, const char *str) { 
    struct lnode *n = malloc(sizeof(struct lnode)); 
    n->item = malloc(sizeof(char)*(strlen(str)+1)); 
    strcpy(n->item, str); 
    n->next = NULL; 
    if (sq->length == 0) { 
     sq->front = n; 
     sq->back = n; 
    } else { 
     sq->back->next = n; 
     sq->back = n; 
    } 
    sq->length++; 
} 

char *sq_remove_front(StrQueue sq) { 
    if (sq->front == NULL) { 
     return NULL; 
    } else { 
     struct lnode *f = sq->front; 
     char *temp = sq->front->item; 
     sq->front = sq->front->next; 
     sq->length--; 
     //Delete the line below will not cause an error of not free all memory 
     free(f->item); 
     free(f); 
     return temp; 
    } 
} 

int sq_length(StrQueue sq) { 
    return sq->length; 
} 

Здесь я хочу сделать strqueue похожим списком, но когда я его использую, он всегда говорит, что я пытаюсь удвоить что-то. Какая часть моего кода неверна? Есть ли утечка памяти или что-то неправильное в распределении памяти?C - double free

+0

Случайные точки: 'sizeof (char) == 1' always; нет смысла умножать его. Кроме того, 'malloc' +' strcpy' => 'strdup'. –

+0

Можете ли вы показать нам пример тестового примера, который запускает двойной бесплатный? –

+0

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

ответ

4

В

struct lnode *f = sq->front; 
char *temp = sq->front->item; 
sq->front = sq->front->next; 
sq->length--; 
//Delete the line below will not cause an error of not free all memory 
free(f->item); 
free(f); 
return temp; 

Она возвращает указатель на tempfree д памяти в free(f->item), чтение строка через этот указатель не определенно поведение. И если вы free это будет двойной free. В принципе, возвращаемый указатель бесполезен.

Исправление будет состоять в том, чтобы не делать free(f->item) в этой функции. Вызывающему нужно будет освободить указатель на строку после использования.


Односвязные список лучше всего представлено:

struct lnode *head, **tail; 

инициализирован как:

head = NULL; 
tail = &head; 

В этом случае нет необходимости в специальной обработке пустого списка на добавление. Прикрепление всегда:

*tail = n; 
tail = &n->next; 

Удаление от фронта:

struct lnode *n = head; 
if(head) { 
    head = head->next; 
    if(!head) 
     tail = &head; 
} 
return n; 
+0

Вот еще вопрос, теперь для remove_front, как я могу вернуть char * без утечки памяти? Если у меня есть указатель, указывающий на исходный элемент, а затем я освобождаю элемент, он ничего не вернет, но когда я создам новый символ *, после его возвращения он не будет освобожден, так это приведет к утечке памяти? –

+0

Обновлен ответ для вас. –

0

Вы могли бы попробовать это в char *sq_remove_front(StrQueue sq):

if (f->item != NULL) { 
    free(f->item); 
    f->item = NULL; 
} 
if (f != NULL) { 
    free(f); 
    sq->front = NULL; 
} 

Это позволит избежать выполнения free() дважды указателей.

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