2015-04-08 3 views
1

Я читаю файл строки за строкой (файл содержит только одну строку для тестирования), и я создаю struct для каждой строки и добавляя, что struct к предопределенному массиву.double free при освобождении структуры в массиве

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

Я разделся программа вниз, насколько я мог, но на free'ing записи массива, я получаю ошибку

*** 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; 

Но я не могу понять, что именно происходит не так.

ответ

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 является двойным указателем.

+0

Хорошо, согласен.Это, конечно, только фиктивная программа, потому что я хочу узнать, как работать с динамическим распределением памяти, например, кто владеет памятью и кто несет ответственность за освобождение ... Я согласен с вашим мнением и полностью согласен. – Max

+0

Argh ... спасибо: D – Max

+0

Благодарим вас за то, что вы также указали на другие недостатки. У меня есть чему поучиться. – Max

1

Вы теряете память malloc(), так как вы копируете ее в свой массив фактических структур (persons). Ваш код не должен использовать malloc(), и, конечно же, не free() нравится.

Было бы больше смысла, чтобы иметь массив указателей:

Person *persons[10]; 

Тогда есть функция, которая вызывает malloc() вернуть вновь выделенную память, так что вы можете сделать persons[line_num] = person_create(line_num, 2, line);. Затем вам необходимо пройти и free() их всех.

+0

Пункт моей программы заключается в том, что я хочу узнать, как использовать динамическое распределение памяти, я знаю, что это, вероятно, выглядит немного странно/излишне. ;) – Max

1

Ваш код показывает неопределенное поведение. Вы decalred

Person persons[1] = {}; 

и позже, вы используете

persons[line_num] = *person; 

, который вызывает из связанного доступа к памяти, которая, в свою очередь, вызывает undefined behaviour.

+0

Думаю, теперь я лучше понимаю, можете ли вы, пожалуйста, немного расширить доступ к «доступному доступу к памяти»? – Max

+0

@Max Не связанный доступ означает, что вы пытаетесь получить доступ к памяти, которая не выделена. Чтобы упростить, вы не можете получить доступ к 'person [1]', так как индекс c массива равен '0'. :-) –

Смежные вопросы