我正在尝试使用“固定内存方案”并预先分配内存,并通过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()一次?
非常感谢,请提供百万美元,请以最少的变动提供简洁的答案。
问题是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!
随时要求进一步的澄清和/或解释。