C. double free or corruption (!prev) 中止(核心转储)

C. double free or corruption (!prev) Aborted (core dumped)

我正在尝试使用 "fixed memory scheme" 并预分配内存并通过 alloc、init、free 方式尽可能多地重复使用它。

free() 只会在关机时调用,但我想测试多次迭代。

虽然我调用了alloc函数bn_tree_alloc_node_space_heap()和init函数bn_tree_init_node_heap(),但我只能调用free函数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;
}

这是我 expect/want:

的输出
alloc
init
free
alloc
init
free
alloc
init
free
alloc
init
free

但是我得到这个 output/error:

alloc
init
free
alloc
init
double free or corruption (!prev)
Aborted (core dumped)
  1. 如何解决这个问题?

  2. 我不能随心所欲地多次执行 alloc、init、free(只要我在 free 之前调用 alloc)或者我只能执行一次 alloc(),然后执行多次 init( ), free() 一次?

非常感谢,请提供简明的答案,并进行最少的改动。

问题是您的 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!

随时要求进一步澄清 and/or 解释。


1 编辑:还有其他方法(有些人可能认为 更好 方法)来实施您的系统,以及您的其他 'minor' 问题代码。但是,您 明确地 要求 "concise answers with minimal changes," 所以我已尽力满足该要求!