如何在C

时间:2019-10-03 15:29:56

标签: c linked-list valgrind free doubly-linked-list

我正在用C创建一个链表,需要一些帮助来释放它。元素的结构和整个列表如下所示:

typedef struct node_ {
    int num;
    struct node_ *next;
    struct node_ *prev;
} element;


typedef struct list_ {
    element **first;
    element **last;
    int *e_count;
} list;

这是我释放列表的问题。这段代码可以正常工作:

void wipe(list l) {
    element *p = *l.first;
    element *t;

    while (p) {
        t = p;
        p = p->next;
        free(t);
    }

    *l.first = NULL;
    *l.last = NULL;
    *l.e_count = 0;
}

但是当我尝试使用双指针时,我开始从valgrind收到 InvalidRead 错误:

void wipe(list l) {
    element **p = l.first;
    element **t = l.first;

    while (*p) { // InvalidRead here after "free(*t);"
        *t = *p;
        p = &(*p)->next;
        free(*t);
    }

    *l.first = NULL;
    *l.last = NULL;
    *l.e_count = 0;
}

这是可预期的,因为在这种情况下,tp指向free()正在使用的同一地址。我想知道如何解决这个问题,以及它是否比第一种使用单个指针的情况更好。

谢谢您的帮助!

代码示例:

#include <stdlib.h>
#include <stdio.h>


typedef struct node_ {
    int num;
    struct node_ *next;
    struct node_ *prev;
} element;


typedef struct list_ {
    element **first;
    element **last;
    int *e_count;
} list;


list new_list();
void delete_list(list l);

element *alloc_element(int n);

int append(list l, int n);
void wipe(list l);


int main() {
    list l = new_list();
    append(l, 5);
    append(l, 7);
    delete_list(l);
}


list new_list() {
    element **first = malloc(sizeof(element*));
    element **last = malloc(sizeof(element*));
    int *n = malloc(sizeof(int));
    *first = NULL;
    *last = NULL;

    list list = {first, last, n};
    return list;
}


void delete_list(list l) {
    wipe(l);
    free(l.first);
    free(l.last);
    free(l.e_count);
}


element *alloc_element(int n) {
    element *e = malloc(sizeof(element));
    if (!e) {
        return NULL;
    }
    e->next = NULL;
    e->prev = NULL;
    e->num = n;
    return e;
}


int append(list l, int n) {
    element **p = l.first;
    element *e = alloc_element(n);
    if (!e) {
        return 1;
    }

    while (*p) {
        if (!(*p)->next) {
            e->prev = *p;
        }
        p = &(*p)->next;
    }

    *p = e;
    *l.last = e;
    ++*l.e_count;
    return 0;
}


void wipe(list l) {
    element *p = *l.first;
    element *t;

    while (p) {
        t = p;
        p = p->next;
        free(t);
    }

    *l.first = NULL;
    *l.last = NULL;
    *l.e_count = 0;
}

1 个答案:

答案 0 :(得分:1)

由于您需要使用函数来修改list,因此需要将指向list的指针传递给函数。另外,您的代码中似乎对避免使用双指针有很多困惑。这是修正了所有混乱的代码的整理版本:

#include <stdlib.h>
#include <stdio.h>


typedef struct node_ {
    int num;
    struct node_ *next;
    struct node_ *prev;
} element;


typedef struct list_ {
    element *first;
    element *last;
    int e_count;
} list;


list *new_list(void);
void delete_list(list *l);

element *alloc_element(int n);

int append(list *l, int n);
void wipe(list *l);


int main(void) {
    list *l = new_list();
    append(l, 5);
    append(l, 7);
    delete_list(l);
}


list *new_list(void) {
    list *l = malloc(sizeof(list));
    if (!l) {
        return NULL;
    }
    l->first = NULL;
    l->last = NULL;
    l->e_count = 0;
    return l;
}


void delete_list(list *l) {
    if (l != NULL) {
        wipe(l);
        free(l);
    }
}


element *alloc_element(int n) {
    element *e = malloc(sizeof(element));
    if (!e) {
        return NULL;
    }
    e->next = NULL;
    e->prev = NULL;
    e->num = n;
    return e;
}


int append(list *l, int n) {
    element *e = alloc_element(n);
    if (!e) {
        return 1;
    }
    if (l->last) {
        l->last->next = e;
    } else {
        l->first = e;
    }
    e->prev = l->last;
    l->last = e;
    ++l->e_count;
    return 0;
}


void wipe(list *l) {
    element *p = l->first;
    element *t;

    while (p) {
        t = p;
        p = p->next;
        free(t);
    }

    l->first = NULL;
    l->last = NULL;
    l->e_count = 0;
}