释放数组中的结构时双重释放

double free when freeing structure in array

我正在逐行读取文件(该文件只包含一行用于测试),我正在为每一行创建一个 struct,并将 struct 添加到预定义的数组。

#define _GNU_SOURCE

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


typedef struct {
    int age;
    int weight;
    char *name;
} Person;


int person_create(Person **person, unsigned int age, unsigned int weight, char *name)
{   
    *person = malloc(sizeof(Person));

    if (person == NULL) {
        return 0;
    }

    return 1;
}

void person_free(Person *person)
{
    free(person);

    return;
}

int main(void)
{
    FILE *input_file = NULL;

    input_file = fopen("names.txt", "r");
    assert(input_file != NULL);

    char *line = NULL;
    size_t _ = 0;
    ssize_t line_len = 0;
    Person persons[1] = {};
    int line_num = 0;

    while ((line_len = getline(&line, &_, input_file)) != -1) {
        if (line[line_len - 1] == '\n') {
            line[line_len - 1] = '[=10=]';  
        }

        Person *person = NULL;
        person_create(&person, line_num, 2, line);

        persons[line_num] = *person;

        line_num++;        
    }

    free(line);

    printf("lines read %d\n", line_num);

    for (int i = 0; i < 1; i++) {
        person_free(&persons[i]);
    }

    return 0;
}

我尽可能地精简了程序,但在释放数组条目时,出现错误

*** Error in `./prog': double free or corruption (out): 0x00007fff7ace9f10 ***
Aborted (core dumped)

如果我省略了对 free_person 的调用,那么 valgrind 会报告失忆。

我很确定这与我如何将每一行的人分配给数组有关

    Person *person = NULL;
    person_create(&person, line_num, 2, line);

    persons[line_num] = *person;

但我似乎无法理解到底出了什么问题。

您正在丢失 malloc()ed 内存,因为您将它复制到您的实际结构数组 (persons) 中。您的代码不需要使用 malloc(),当然也不需要像它那样使用 free()

拥有一个指针数组会更有意义:

Person *persons[10];

然后有函数调用malloc()return新分配的内存,这样就可以persons[line_num] = person_create(line_num, 2, line);了。 然后你需要通过并free()他们全部。

您的程序有一些严重的未定义行为:一旦 line_num 大于零,您将写入内存 persons[] 数组之外。需要分配足够多的元素,还要让它成为一个指针数组:

Person *persons[100]; // or some other MAX

一旦将 persons[] 设为指针数组,就会清楚为什么 free(&persons[i])persons[line_num] = *person 不正确(编译器应该针对赋值发出警告)。

此外,malloc的检查结果不正确:

if (person == NULL) {
    return 0;
}

您应该检查 *person,而不是 person,因为 person 是双指针。

您的代码显示未定义的行为。您已贴花

 Person persons[1] = {};

及以后,您正在使用

persons[line_num] = *person;

这会导致越界内存访问,进而调用 undefined behaviour