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

时间:2015-04-08 12:12:12

标签: c arrays memory-management

我正在逐行读取文件(该文件只包含一行用于测试),我为每一行创建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] = '\0';  
        }

        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;

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

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:1)

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

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

Person *persons[10];

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

答案 2 :(得分:1)

您的代码显示未定义的行为。你已经死了

 Person persons[1] = {};

以后,你正在使用

persons[line_num] = *person;

导致超出范围的内存访问,而后者又调用undefined behaviour