Прав ли Валгринд? Потеряна ли память? - PullRequest
0 голосов
/ 20 июня 2011
typedef struct Model
{
    int recordId;
    char *name;
}Model;

typedef struct ModelArray
{
    //keeps the size that the array was initially create with. When more elements are needed
    //we use this to add that many more elements
    int originalSize;
    //total number of elements that can be used
    int elements;
    //total number of elements used
    int count;
    //the actual array is stored here
    Model *source;
}ModelArray;

void initModelArray(ModelArray *array, int numberOfElements)
{
    array->originalSize = numberOfElements;
    array->elements = numberOfElements;
    array->count = 0;
    array->source = malloc(sizeof(Model)*numberOfElements);//0 bytes in 3 blocks are definitely lost in loss record 1 of 65
}

void deallocModelArray(ModelArray *array)
{
    if(array == NULL)
        return;

    array->elements = 0;
    array->count = 0;
    free(array->source);
    array->source = NULL;
    free(array);
}

main(int argc, const char * argv[])
{
    ModelArray *models = malloc(sizeof(ModelArray));
    initModelArray(models, 10);
    deallocModelArray(models);
}

Что потеряно? Код выглядит хорошо для меня. Я уверен, что мог бы сначала сказать array-> source = NULL, но это не нужно, верно?

Ответы [ 2 ]

7 голосов
/ 20 июня 2011

Чтобы правильно освободить эти структуры, вам нужно сделать следующее в следующем порядке:

free(models->source);
free(models);

Если вы делаете что-то еще, вы теряете память.

Редактировать:

ОК, увидев структуру Model, вы, вероятно, утечка имен, или, по крайней мере, Valgrind думает, что вы делаете, потому что вы освобождаете структуру ModelArray, которая содержит указатель на структуру Model, которая содержит char *, которыйсначала вы не освобождаетесь.

Итак:

int i;
for( i=0; i<models->originalSize; i++ ) {
    if( models->source[i]->name != NULL ) {
        free( models->source[i]->name );
    }
}
free(models->source);
free(models);

И было бы неплохо использовать calloc () вместо malloc () при выделении моделей-> source в первомместо.Это установит все указатели имен на 0. Без этого тест для models-> source [i] -> name, отличное от NULL, может завершиться ошибкой, если имя содержит некоторый мусор (поскольку использование неинициализированной памяти приводит к неопределенному поведению.)

2 голосов
/ 20 июня 2011

Э-э ... Да, память потеряна.Конечно, это потеряно, так как вы "пропустили код деллока"!

Как вы могли ожидать, что кто-нибудь ответит на ваш вопрос, когда вы "не указали код освобождения"?Сама суть вашего вопроса в том, верен ли ваш код деэллока.И вы решили оставить это без внимания?

Кроме того, в вашем коде есть немало вещей, которые не имеют большого смысла.Что должно означать

typedef struct ModelArray {
  ...
  Model *source; 
  ...
} Model;

?Почему вы печатаете struct ModelArray как Model?Фактически, ваш код даже не скомпилируется, поскольку Model * используется внутри структуры, где он еще не объявлен.Вы также используете тип ModelArray в своем коде, хотя в действительности такого типа нет.У вас есть struct ModelArray, но не просто ModelArray.Код, который вы разместили, не является реальным кодом.Разместите реальный код, пожалуйста.(Очевидно, это должно было быть typedef struct ModelArray { ... } ModelArray; с Model, определенным в другом месте.)

Наконец, в качестве несвязанной заметки, // comments является функцией C99.В C99 тип возвращаемого значения функции не может быть опущен (нет правила «неявного int» в C99), что означает, что вы должны объявить вашу main функцию как int main.

...