调用免费时出错:双重免费或损坏,损坏的大小与 prev_size,收到信号 6

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

我在分配的内存块上调用 free 时收到错误。 根据我的代码,我得出以下 MWE:

(注意,free被注释掉了,调用会报错)

#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;
}

我有一个结构 foo2,它包含一个指向结构数组 foo1 的指针。我使用不同的函数分配内存和初始化变量,因为在我的用例中,我需要解析不同的数据文件。我不想有一个巨大的代码块。

但是,当我拨打免费电话时,我收到错误消息。我使用 GCC 7.5.0。 对于可能导致此问题的原因,我将不胜感激。

P.S。在我的原始程序中,错误取决于调用 free 的位置。在这个 MWE 中,它不是。

非常感谢。

您分配的内存量有误:

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

您想创建一个 foo1 的数组,但您在这里使用 sizeof(foo2)foo2 的数组分配 space。由于 foo2 小于 foo1,您写入已分配内存的末尾触发 undefined behavior

将此更改为:

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

并且在 完成使用之前不要调用 free,在这种情况下,“位置 3”是您想要释放两者的地方 myfoo2->myfoo1smyfoo2.

P.S。我在我的原始代码中找到了问题的根本原因——独立于 MWE。该错误是由 两次释放分配的内存 引起的。在进一步追踪问题之后,GCC 打印出错误 free(): double free detected in tcache 2,这让我走上了正确的轨道。