I know that this question exists in other places like:
pointer being freed was not allocated in C error: pointer being freed was not allocated
but, I'm still very confused. Errors seem to be associated with things like "modifying the original pointer returned by malloc" and "failing to malloc before freeing". I just don't see how these reasons apply to my program.
I'm writing a dynamically allocated array of strings:
#include <stdio.h>
#include <stdlib.h>
#define NLETTERS 25
typedef struct {
char** array;
size_t used;
size_t size;
} array_t;
array_t* initArray(size_t initialSize) {
array_t* a = malloc(sizeof(array_t));
a->array = malloc(initialSize*sizeof(char*));
a->used = 0;
a->size = initialSize;
int i;
for(i = 0; i < initialSize; i++) {
a->array[i] = malloc(sizeof(char) * NLETTERS);
}
return a;
}
void insertArray(array_t *a, char* element) {
if (a->used == a->size) {
a->size *= 2;
a->array = realloc(a->array, a->size * sizeof(char*));
int i;
for(i = (int)a->used; i < a->size; i++) {
a->array[i] = malloc(sizeof(char) * NLETTERS);
}
}
a->array[a->used++] = element;
}
void freeArray(array_t *a) {
int i;
for(i = 0; i < a->size; i++) {
free(a->array[i]);
}
free(a->array);
free(a);
a->array = NULL;
a->used = a->size = 0;
}
void print_array(array_t *a) {
int i;
for(i = 0; i < a->size; i++) {
printf("%s\n", a->array[i]);
}
}
int main(int argc, const char * argv[]) {
array_t *a;
a = initArray(2);
insertArray(a, "hello");
insertArray(a, "how are you");
print_array(a);
insertArray(a, "yup");
insertArray(a, "you know it");
print_array(a);
freeArray(a);
return 0;
}
When I attempt to "free", I get the error: "pointer being freed was not allocated" right at
free(a->array[0])
in the first iteration of the for-loop in freeArray();
Help would be greatly appreciated.
In your code, by saying
a->array[a->used++] = element;
you're overwriting the allocated memory by malloc()
, so, later while passing it to free()
causes the issue.
Related, quoting C11
, chapter §7.22.3.3, The free
function, (emphasis mine)
The
free
function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. Ifptr
is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
Also, at a later point, this causes memory leak, as the memory allocated by malloc()
is not getting free()
-d, actually.
Solution: You should use strcpy()
to copy the content into the allocated memory.