C。双重释放或损坏(!prev)中止(核心已转储)

问题描述 投票:0回答:1

我正在尝试使用“固定内存方案”并预先分配内存,并通过alloc,init,free方式尽可能多地重用它。

free()仅在关机时调用,但是我想测试许多迭代。

尽管我调用了分配函数bn_tree_alloc_node_space_heap()和初始化函数bn_tree_init_node_heap(),但我只能调用一次自由函数bn_tree_free_node_space

下面是我的内存管理的完整可复制片段,maint_test.c:

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <float.h>
#define BN_TREE_HEAP_SIZE 100

/*variables internal*/
typedef struct bntree_internals;

/*bn_tree_node is single bntree_t leaf*/
typedef struct bn_tree_node {
    struct bn_tree_node* left;
    struct bn_tree_node* right;
    float* dataset;
    float distance_to_neighbor;
    int visited;
    int heap_index;
} bn_tree_node;

/*tree*/
typedef struct {
    /*in order to  keep track of the bn-tree root*/
    bn_tree_node* _root;
    /*pointer to internal variables struct*/
    struct bntree_internals* _internals;

} bntree_t;


/*bn tree leaf nodes heap*/
bn_tree_node* node_processing_space = NULL;

/*leaf nodes*/
void bn_tree_alloc_node_space_heap(int max_dimensions);
bn_tree_node*
get_pre_allocated_bn_tree_node_heap();
void bn_tree_init_node_heap(bn_tree_node* nodes, int max_dimensions);
void bn_tree_free_node_space(bn_tree_node* nodes);

int main(int argc, char** argv) {

    /*PROBLEM:called the alloc,init,free cycle several times, problem, 
     getting seg fault on 2nd call of free()*/
    bn_tree_alloc_node_space_heap(3);
    assert(get_pre_allocated_bn_tree_node_heap());
    printf("alloc\n");
    bn_tree_init_node_heap(node_processing_space, 3);
    printf("init\n");
    bn_tree_free_node_space(node_processing_space);
    printf("free\n");

    bn_tree_alloc_node_space_heap(3);
    assert(get_pre_allocated_bn_tree_node_heap());
    printf("alloc\n");
    bn_tree_init_node_heap(node_processing_space, 3);
    printf("init\n");
    bn_tree_free_node_space(node_processing_space);
    printf("free\n");

    bn_tree_alloc_node_space_heap(3);
    assert(get_pre_allocated_bn_tree_node_heap());
    printf("alloc\n");
    bn_tree_init_node_heap(node_processing_space, 3);
    printf("init\n");
    bn_tree_free_node_space(node_processing_space);
    printf("free\n");

    bn_tree_alloc_node_space_heap(3);
    assert(get_pre_allocated_bn_tree_node_heap());
    printf("alloc\n");
    bn_tree_init_node_heap(node_processing_space, 3);
    printf("init\n");
    bn_tree_free_node_space(node_processing_space);
    printf("free\n");



    return (EXIT_SUCCESS);
}

void bn_tree_alloc_node_space_heap(int max_dimensions) {
    if (NULL == node_processing_space) {
        node_processing_space = (bn_tree_node*) calloc(BN_TREE_HEAP_SIZE, sizeof (bn_tree_node));


        //TODO: bn_tree_set_k_dimensions (max_dimensions);

        int i = 0;
        for (; i < BN_TREE_HEAP_SIZE; i++) {
            node_processing_space[i].dataset = (float*) calloc(max_dimensions, sizeof (float));

        }

        //bn_heap_tail_index = bn_heap_head_index = 0;
    }
}

bn_tree_node* get_pre_allocated_bn_tree_node_heap() {
    return node_processing_space;
}

void bn_tree_init_node_heap(bn_tree_node* nodes, int max_dimensions) {

    int i = 0;
    int c = 0;
    for (; i < BN_TREE_HEAP_SIZE; i++) {

        /*reset  values */
        if (NULL != nodes[i].dataset) {
            c = 0;
            for (; c < max_dimensions; c++) {
                nodes[i].dataset[c] = FLT_MIN;
            }
        }
        nodes[i].visited = 0;
        nodes[i].distance_to_neighbor = FLT_MAX;
        nodes[i].left = NULL;
        nodes[i].right = NULL;
        nodes[i].heap_index = -1;

    }
}


/*PROBLEM is subsequent call to free(), but if I alloc again why cant I free again?*/
void bn_tree_free_node_space(bn_tree_node* nodes) {
    int i = 0;
    for (; i < BN_TREE_HEAP_SIZE; i++) {
        if (nodes[i].dataset) {
            free(nodes[i].dataset);
        }
    }

    free(nodes);
    nodes = NULL;
}

这是我期望/想要的输出:

alloc
init
free
alloc
init
free
alloc
init
free
alloc
init
free

但是我得到这个输出/错误:

alloc
init
free
alloc
init
double free or corruption (!prev)
Aborted (core dumped)

1)如何解决此问题?

2)我不能随意分配alloc,init,free(只要我在free之前先叫alloc),或者我只能做一次alloc(),然后做一次init(),free()一次?

非常感谢,请提供百万美元,请以最少的变动提供简洁的答案。

c memory-management ansi-c
1个回答
0
投票

问题是bn_tree_free_node_space函数将指针变量的copy作为其参数-也就是说,您正在传递指针by value-因此,行nodes = NULL;在该函数的末尾,仅将local变量设置为NULL,并且不更改[>]的值node_processing_space变量。

要解决此问题(只需对代码逻辑1

进行最少的更改),您需要向该函数传递指向指针的指针,然后在函数中取消引用。因此,您的函数应如下所示:
void bn_tree_free_node_space(bn_tree_node** nodes) // Argument is pointer-to-pointer
{
    int i = 0;
    for (; i < BN_TREE_HEAP_SIZE; i++) {
        if ((*nodes)[i].dataset) { // Now we need to use (*nodes) to get the underlying pointer
            free((*nodes)[i].dataset); // ... same here
        }
    }

    free(*nodes); /// ... and here
    *nodes = NULL;
}

当然,您还需要更改函数原型(就在main之前)以匹配新定义:

void bn_tree_free_node_space(bn_tree_node** nodes); // Must match definition!

此外,您(显然)将需要更改对该函数的调用,以传递node_processing_space指针的地址

bn_tree_free_node_space(&node_processing_space); // Likewise for the other 3 calls!

随时要求进一步的澄清和/或解释。


1编辑:还有其他方式(有些人可能会争论[[better方式)来实现您的系统,以及代码中的其他“次要”问题。但是,您确实要求[[明确地进行“更改最少的简洁答案”,因此,我竭力遵守该要求!
© www.soinside.com 2019 - 2024. All rights reserved.