Почему free () - моя память malloc () - ed в другой функции вызывает сбой? - PullRequest
0 голосов
/ 06 октября 2018

У меня есть связанный список структур и функций для добавления, удаления и создания данных из него.Теперь проблема возникает, когда я пытаюсь освободить () данные, которые я выделил в функции создания.Программа работает нормально, если я удаляю часть своего кода, где я освобождаю память, но затем я не освобождаю память.

Структура:

typedef struct carinfo_t
{
    char * brand;
    char * model;
    int year;
    float value;
    struct carinfo_t * next;
} carinfo_t;

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

struct carinfo_t *createCarinfo(char *brand, char *model, int year, float value)
{
    carinfo_t *newInfo = (carinfo_t *) malloc (sizeof(newInfo));
    newInfo->brand = malloc (sizeof(brand));
    newInfo->model = malloc (sizeof(model));

    if (!newInfo)
    {
        printf("createCarinfo: error: no space left\n");
    }
    else
    {
        strcpy(newInfo->brand, brand);
        strcpy(newInfo->model, model);
        newInfo->year = year;
        newInfo->value = value;
        newInfo->next = NULL;
    }
    return newInfo;
}

Свободная функция:

void freeCarinfo(struct carinfo_t *carinfo)
{
    if(carinfo->brand != 0)
    {
        free(carinfo->brand);
        carinfo->brand = 0;
    }
    if(carinfo->model != 0)
    {
        free(carinfo->model);
        carinfo->model = 0;
    }
    if(carinfo != 0)
    {
       free(carinfo);
       carinfo = 0;
    }
}

И функция freeCarinfo () вызывается моей функцией removeCarinfo (), которая в основном обеспечивает правильное сопоставление всех элементов в очереди при удалении элементов, которые я ищу.

Что яхочу сделать сейчас, чтобы иметь возможность освободить память, которую я дал программе с

carinfo_t *newInfo = (carinfo_t *) malloc (sizeof(newInfo));
newInfo->brand = malloc (sizeof(brand));
newInfo->model = malloc (sizeof(model));

Ответы [ 2 ]

0 голосов
/ 06 октября 2018

Во-первых, когда вы выделяете пространство для данных, вы совершаете распространенную ошибку:

newInfo->brand = malloc (sizeof(brand));

Это выделяет достаточно места для хранения указателя на char, а не самих данных.Затем вы пытаетесь скопировать в него данные:

strcpy(newInfo->brand, brand);

, что вполне может записать больше данных, чем было создано для вас.

Вам нужно создать достаточно места для всей строкиплюс маркер конца строки \0:

newInfo->brand = malloc (strlen(brand) + 1);

И вам это тоже понадобится где-то:

#include <string.h>

Во-вторых, когда вы сравниваете указатель на 0, традиционный способ C - использовать NULL вместо 0 (или не использовать вовсе).Это (в основном) тот же эффект, но более понятно, что вы выполняете сравнение указателей.

В-третьих, в freeCarinfo вы используете carinfo, а затем проверяете, является ли оно NULL (0),Вам действительно нужно знать, может ли функция вызываться со значением NULL, в этом случае вы чаще всего не используете carinfo->brand, или это определенно не NULL, и в этом случае вам не нужен последний тест.

В-четвертых, как уже упоминалось другими, вы выделяете newInfo способом, который не дает нужного количества места:

carinfo_t *newInfo = (carinfo_t *) malloc (sizeof(newInfo));

Что вам, вероятно, нужновместо этого:

carinfo_t *newInfo = malloc (sizeof(carinfo_t));

или даже лучше:

carinfo_t *newInfo = malloc (sizeof(*newInfo));

Таким образом, здесь много и много неправильного, поэтому вы расстраиваетесь.Перечитайте информацию об указателях и динамическом размещении и по-новому взгляните на ваш код в зависимости от того, что вы узнали.

0 голосов
/ 06 октября 2018

Посмотрите на возвращаемые значения ваших sizeof() операторов.Я думаю, вы обнаружите, что вы выделяете достаточно байтов для хранения указателей , а не самих структур или символов.sizeof() так сложно.

malloc() Реализации могут очень хорошо выделить некоторые дополнительные байты для внутреннего обслуживания.Если вы выделяете слишком мало памяти и начинаете писать поверх этих внутренних структур, вы попадаете в неопределенную область поведения, и это видно, когда вы пытаетесь free() этот блок, потому что free(), вероятно, захочет использовать эти данные.

Редактировать: см. Обсуждение ниже для идиоматического решения и обсуждения от @David Bowling, к которому я отношусь: carinfo_t *newInfo = malloc (sizeof *newInfo);

...