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



我逐行读取一个文件(该文件只包含一行用于测试),并为每行创建一个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] = '';  
        }
        Person *person = NULL;
        person_create(&person, line_num, 2, line);
        persons[line_num] = *person;
        line_num++;        
    }
    free(line);
    printf("lines read %dn", 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;

但我似乎不明白到底出了什么问题。

您的程序有一些严重的未定义行为:一旦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;

这会导致超出绑定的内存访问,进而调用未定义的行为。

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

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

Person *persons[10];

然后让调用malloc()的函数返回新分配的内存,这样就可以执行persons[line_num] = person_create(line_num, 2, line);然后你需要遍历并free()它们。

最新更新