【问题标题】:C. double free or corruption (!prev) Aborted (core dumped)C. double free or corruption (!prev) Aborted (core dumped)
【发布时间】:2020-04-16 20:15:32
【问题描述】:

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

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

虽然我调用了我的alloc函数bn_tree_alloc_node_space_heap()&init函数bn_tree_init_node_heap(),但我只能调用一次free函数bn_tree_free_node_space

下面是我的内存管理的完整可重现的 sn-p,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】:

    问题在于您的bn_tree_free_node_space 函数将指针变量的副本 作为其参数 - 也就是说,您正在传递指针按值 -因此,该函数末尾的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 编辑:还有其他方法(有些人可能认为更好 方法)可以实现您的系统,以及您的代码中的其他“小”问题。但是,您确实明确要求“以最小的更改简洁的答案”,因此我已努力满足该要求!

    【讨论】:

    • 谢谢。因此,如果一个指针被传递给一个带有指针*签名的函数,那么指针会自动取消引用并传入值?
    • @cyber101 不是这样。没有自动取消引用,但指针的处理方式与按值传递的任何其他类型的参数一样:您的函数可以更改它指向的内容,但不能更改其实际值。在您的情况下,您希望(需要)更改指针的 value (即为其分配一个新的 NULL 地址值),因此您必须将指针传递给指针。
    • 知道了,谢谢。如果我想使用像bn_tree_init_node_heap(get_pre_allocated_bn_tree_node_heap(), 3); 这样的getter 函数传入node_processing_space 怎么办?调用bn_tree_init_node_heap(&amp;get_pre_allocated_bn_tree_node_heap(), 3); 会导致编译错误“lvalue...”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-30
    • 2014-03-06
    • 2013-09-14
    • 2020-07-23
    • 2020-08-14
    • 2021-05-03
    相关资源
    最近更新 更多