0

I am learning C and I can't free a dynamically allocated array of structs. Here is my sample code:

typedef char Str50[50];

typedef struct exam {
    Str50 firstname;
    Str50 lastname;
    Str50 className;
    int score;
    Str50 date;
} Exam;

Exam *examDB

size_t allocateAndFreeTheStructArray {

    size_t numRecs = 100; //let's say the array contains 100 elements
    examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory

    // the code below tries to free what malloc allocated
    for (size_t i = 0; i < numRecs; i++) {
        free(&examDB[i]);
    }
    free(examDB);
}

When I compile this for windows, everything works fine (it seems). When I compile the same piece of code on my mac using xcode, I get an error that says: "malloc: *** error for object 0x7fae610060d0: pointer being freed was not allocated"

How is that possible? I used malloc to create the array... What am I missing here?

4 Answers 4

4

You allocated a flat array of 100 objects. You're then trying to free each object separately and the list at the end - that's a pattern used when you have an array of pointers to objects. In your case, you can't free just one object in a flat array.

You have two options. Keep the flat array and just call free once:

size_t numRecs = 100; 
examDB = malloc(numRecs * sizeof * examDB); 

free(examDB);

Or change examDB to a pointer to pointer to Exam to keep a list of pointers:

Exam **examDB;

and then this would be the valid code:

size_t numRecs = 100; 
examDB = malloc(numRecs * sizeof * examDB); 

for (size_t i = 0; i < numRecs; i++) {
    examDB[i] = malloc(sizeof ** examDB);
}

for (size_t i = 0; i < numRecs; i++) {
    free(&examDB[i]);
}
free(examDB);

BTW, this must be one of the most confusing malloc invocations I've ever seen:

malloc(numRecs * sizeof * examDB)
Sign up to request clarification or add additional context in comments.

3 Comments

This line examDB = malloc(numRecs * sizeof * examDB); is confusing. You meant examDB = malloc(numRecs * sizeof (*examDB) ); . Right ?
Yes, but it's taken from the question as-is.
2

You need a free for each malloc. How many mallocs you have? 1, so how many free you need? Just 1.

You are allocating an array of 100 * sizeof(examDB) elements, which is dynamic but each element is a examDB, not a pointer to an examDB so you just need to free the whole array.

You would have required to free each element of the array if you had something like

// 1 malloc
examDB** array = malloc(sizeof(examDB*) * 100);

// 100 malloc
for (int i = 0; i < 100; ++i)
  examDB[i] = malloc(sizeof(examDB));

...

// 100 free
for (int i = 0; i < 100; ++i)
  free(examDB[i]);

// 1 free
free(examDB);

Comments

2

You allocated an array of objects. You can't free them by elements. What you can do is just free examDB itself:

 free(examDB);

The reason to do this is, as I said before, you are allocating a whole array of null values, as this code you posted states:

examDB = malloc(numRecs * sizeof * examDB); 

What you can do to free element by element is to initialize your allocated elements like this:

for (int i = 0; i < 100; ++i)
  examDB[i] = malloc(sizeof(examDB));

Here is a C++ reference for malloc.

Tip: I have never seen this malloc invoked like this:

malloc(numRecs * sizeof * examDB); 

It's more common to put it this way:

malloc(numRecs * sizeof(examDB)); 

1 Comment

I agree, rhis 'style': malloc(numRecs * sizeof * examDB); is an abomination.
0
examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory

This expression allocates a single contiguous block of numRecs * sizeof *examDB, and sizeof *examDB is the same as sizeof struct exam. So at this point you can use examDB much in the same way as if it was declared struct exam examDB[numRecs].

Calls to free should be paired with calls to malloc and since you only malloc once, you only need to free once.

 examDB = malloc(numRecs * sizeof * examDB); //this allocates the needed memory
 //...
 free(examDB);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.