如何在 C 中释放树时找出导致内存泄漏的原因

How to find out what causes memory leak while freeing tree in C

我正在尝试找出我的代码的哪一部分导致了内存泄漏。 更具体地说,我已经假设一切从哪里开始,但不知道如何修复它。 这些是我的结构:

typedef struct {
    char *suffix;
    int occurr;
} suff_t;

typedef struct {
    char **prefix;
    suff_t **suffix;
    int n_suff;
    int cap_suff;
} data_t;

typedef struct node {

    data_t *d;
    struct node *left, *right;

} node_t, *tree_t;

以及我使用 malloc / realloc 的函数:

tree_t insert( tree_t t, char **buf, int ngram ) {
    if( t == NULL ) {
            node_t *n = malloc( sizeof *n);
            n->d = create_data(buf, ngram);
            n->left = n->right = NULL;
            return n;
    } else if( cmp_data( t->d, buf, ngram ) > 0  ) {
            t->left = insert( t->left, buf, ngram);
            return t;
    } else if( cmp_data( t->d, buf, ngram ) < 0 ) {
            t->right = insert( t->right, buf, ngram);
            return t;
    } else { // add suffix
            insert_suffix(t->d, buf, ngram);
            return t;
    }

}


void insert_suffix(data_t *data, char **buf, int ngram) {

    int i;
    int cap;

    for(i = 0; i < data->n_suff; i++) {
            if( ! (strcmp(buf[ngram-1], data->suffix[i]->suffix)) ) {
                    data->suffix[i]->occurr++;
                    return;
            }
    }


    if(data->n_suff == data->cap_suff){ // extend table of suffixes
            cap = data->cap_suff;
            data->suffix = realloc(data->suffix, 2*cap*sizeof*data->suffix); // 
            for(i = cap; i < 2*cap; i++)
                    data->suffix[i] = malloc(sizeof(suff_t));
            data->cap_suff *= 2;
    }
            data->suffix[data->n_suff]->suffix = strdup(buf[ngram-1]);
            data->suffix[data->n_suff]->occurr = 1;
            data->n_suff++;
}

data_t * create_data(char **buf, int ngram) {

    int i;

    data_t *newdata = malloc(sizeof*newdata); // 
    newdata->prefix = malloc((ngram-1)*sizeof*newdata->prefix);

    for(i = 0; i < ngram-1; i++) // copy prefix
            newdata->prefix[i] = strdup(buf[i]);

    newdata->suffix = malloc(8*sizeof*newdata->suffix);
    for(i = 0; i < 8; i++)
            //newdata->suffix[i] = malloc(sizeof*newdata->suffix[i]);
            newdata->suffix[i] = calloc(sizeof*newdata->suffix[i], 1);

    newdata->suffix[0]->suffix = strdup(buf[ngram-1]);
    newdata->suffix[0]->occurr = 1;
    newdata->n_suff = 1;
    newdata->cap_suff = 8;

    return newdata;

}

void free_data(data_t *d, int ngram) {

    int i;
    if(d == NULL) return;
    printf("deleting data\n");

    for(i = 0; i < ngram-1; i++)
            free(d->prefix[i]);
    free(d->prefix);

    for(i = 0; i < d->cap_suff; i++) {
            free(d->suffix[i]->suffix);
            free(d->suffix[i]);
    }

    free(d->suffix);
    free(d);
}


void free_tree(tree_t t, int ngram) {

    if( t == NULL) return;
    free_data(t->d, ngram);

    free(t->left);
    free(t->right);
    printf("DELETING NODE\n");
    free(t);

}

Valgrind 提示函数 create_data 和 insert 有问题。 请帮助

Valgrind 指向分配内存的地方,而不是你未能释放它的地方。

cuplrit 几乎可以肯定是 free_tree。树是一种递归数据结构,这意味着您需要递归释放它。您只是在释放根节点。

更改这些行:

free(t->left);
free(t->right);

free_tree(t->left);
free_tree(t->right);

尽管我不确定您会提供什么作为 ngram。大概传原件吧。

关键是你必须向下导航每个分支,在释放节点本身之前从下往上释放。