Yohan Obadia Yohan Obadia - 9 days ago 5
C Question

Free memory for struct corrupt heap

I am trying to implement "my" version of a Safe Array in C and I have a problem of memory leak when I try to free my struct that I created and I can't figure out the problem.

#include <stdio.h>
#include <stdlib.h>

typedef struct safe_array safe_array;
struct safe_array
{
size_t size;
int * safe_array;
};

void init_array(safe_array* safe_array, size_t size, int initial_value)
{
safe_array->safe_array = malloc(sizeof(int) * size);
for (size_t i = 0; i < size; i++)
{
safe_array->safe_array[i] = initial_value;
}
safe_array->size = size;
}

void free_array(safe_array* safe_array)
{
free(safe_array->safe_array);
free(safe_array);
}

int* access_array_element(safe_array* safe_array, size_t index)
{
int out_of_range = 0;
if (index >= safe_array->size)
{
return 0;
}

return &safe_array->safe_array[index];
}

int main()
{

/*Create a safe_array and print its elements*/
safe_array my_safe;
init_array(&my_safe, 5, 2);
for (size_t i = 0; i < my_safe.size; i++)
{
printf("Element %d is %d", i, *access_array_element(&my_safe, i));
}

/*Free the safe_array*/
free_array(&my_safe);

return 0;
}


The problem appears when I try to do
free(safe_array)
but I don't get exactly what's going on. Can't I free it because I never allocated memory to it, if thats the case, how can I completely free that struct ?

The exact message I get is
Debug Assertion Failed
with a link to a
debug_heap.cpp
file.

I need to precise that I want to be able to free the whole struct not only its content.

Answer

The problem is that &my_safe is a pointer to a struct allocated on the stack (by declaring it as a local variable) rather than one allocated on the heap (by using malloc). So you can't call free on it.

Since init_array requires the client code to have already allocated the struct, free_array should likewise require the client code to handle deallocating the struct afterward. Just as init_array only allocates memory for the contents of the array, free_array should only deallocate memory for the contents of the array:

void free_array(safe_array* safe_array)
{
    free(safe_array->safe_array);
}