I'm trying to use a "fixed memory scheme" and pre-allocate memory & reuse it via alloc, init, free fashion as many times as possible.
free() will called at shutdown only, but I want to test many iterations.
Although I call my alloc function bn_tree_alloc_node_space_heap()
& init function bn_tree_init_node_heap()
, I can only call free function bn_tree_free_node_space
once.
Below is a complete reproducible snippet of my memory management, 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;
}
Here is the output that I expect/want:
alloc
init
free
alloc
init
free
alloc
init
free
alloc
init
free
But Im getting this output/error:
alloc
init
free
alloc
init
double free or corruption (!prev)
Aborted (core dumped)
How can fix this?
Can't I do alloc,init,free as many times as I want (as long as I called alloc before free) OR I can do only alloc() once, then many init(), free() once?
Thanks a million & please be kind enough to provide concise answers with minimal changes.
The problem is that your bn_tree_free_node_space
function takes, as its argument, a copy of the pointer variable - that is, you are passing the pointer by value - thus, the line nodes = NULL;
at the end of that function only sets the local variable to NULL
and does not change the value of the node_processing_space
variable.
To fix this (with minimal changes to your code logic1), you need to pass that function a pointer to the pointer, and dereference that in the function. So, your function should look like this:
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;
}
You will, of course, also need to change the function prototype (just before your main
) to match the new definition:
void bn_tree_free_node_space(bn_tree_node** nodes); // Must match definition!
Fruther, you will (clearly) need to change the calls to that function to pass the address of the node_processing_space
pointer:
bn_tree_free_node_space(&node_processing_space); // Likewise for the other 3 calls!
Feel free to ask for further clarification and/or explanation.