Search code examples
cmallocfree

Error on calling free: double free or corruption, corrupted size vs. prev_size, received signal 6


I receive errors when calling free on allocated memory chunks. Based on my code, I derived the following MWE:

(Note, that free is commented out. If it is called, the error will occur.)

#include <stdio.h>
#include <malloc.h>

typedef struct foo1 {
    double v1;
    double v2;
    double v3;
} foo1;

typedef struct foo2 {
    foo1* myfoo1s;
    int num_foo1;
} foo2;

void init_and_set_v1(foo2** myfoo2, int a_num){
    *myfoo2 = malloc(sizeof(foo2));
    (*myfoo2)->num_foo1 = a_num;
    (*myfoo2)->myfoo1s = malloc( (*myfoo2)->num_foo1 * sizeof(foo2) );
    for(int i = 0; i < (*myfoo2)->num_foo1; i ++){
        (*myfoo2)->myfoo1s[i].v1 = 1.0;
    }
    //free( (*myfoo2) -> myfoo1s); //location 1
}

void set_v2_and_v3(foo2* myfoo2){
    for(int i = 0; i < myfoo2->num_foo1; i ++){
        myfoo2->myfoo1s[i].v2 = 2.0;
        myfoo2->myfoo1s[i].v3 = 3.0;
    }
    //free(myfoo2->myfoo1s); //location 2
}

int main(){
   foo2* myfoo2;
   init_and_set_v1(&myfoo2, 10);
   set_v2_and_v3(myfoo2);
   printf("%d\n", myfoo2->num_foo1);
   // ... do other things
   //free(myfoo2->myfoo1s); //location 3
   printf("done.");
   return 0;
}

I have a struct foo2, which contains a pointer to an array of structs foo1. I allocate memory and initialize variables using different functions, because in my use case, I need to parse different data files. I don't want to have a single huge block of code.

However, when I call free, I receive an error. I use GCC 7.5.0. I would appreciate some help as to what might be causing this.

P.S. In my original program the error is dependent from where free is called. In this MWE, it is not.

Thanks a lot.


Solution

  • You're allocating the wrong amount of memory:

    (*myfoo2)->myfoo1s = malloc( (*myfoo2)->num_foo1 * sizeof(foo2) );
    

    You want to create an array of foo1, but you're allocating space for an array of foo2 by using sizeof(foo2) here. Since foo2 is smaller than foo1, you write past the end of allocated memory triggering undefined behavior

    Change this to:

    (*myfoo2)->myfoo1s = malloc( (*myfoo2)->num_foo1 * sizeof(foo1) );
    

    And don't call free until after you've finishing using it, in this case "location 3" is where you want to free both myfoo2->myfoo1s and myfoo2.