C проблема освобождения памяти, ошибка valgrind - PullRequest
0 голосов
/ 18 апреля 2019

Эй, я делаю проект об олимпийской базе данных, в которой ведется учет медалей. Теперь у меня проблема с освобождением памяти (ошибка Valgrind), и я понятия не имею, как мне освободить память?

Ошибка Valgrind исходит из строк:

data[i].country = malloc(strlen(str) + 2);

add_country(countrydata, countryname, i);

Первая функция пытается добавить названия стран в базу данных

    typedef struct Olympia
    {
        char* country;
        int gold;
        int silver;
        int bronze;
    }Olympia;


int add_country(struct Olympia* data, char* str, int i)
    {   
        if (str[0] == '\0') //checking that input is correct
        {
            printf("Error! Try again!\n");
        }

        else
        {
            data[i].country = malloc(strlen(str) + 2);  //allocating memory for country name
            strcpy(data[i].country, str);   //adding country to database
            data[i].gold = 0;   //setting medals to zero
            data[i].silver = 0;
            data[i].bronze = 0;
            i++;
            printf("Country added to database succesfully!\n");
        }
        return i;
    }

Тогда есть основная функция

    int main(void)
    {
        char command;
        int gold = 0;
        int silver = 0;
        int bronze = 0;
        int i = 0;
        char filename[100];

        char* line = (char*)malloc((100) * sizeof(char)); //allocating memory for one stdin line
        char* countryname = (char*)malloc(20 * sizeof(char)); // allocating memory for country name

        struct Olympia* countrydata = malloc(sizeof(struct Olympia) * 1); //allocating memory for structure



        while(1)
        {
            fgets(line, 100, stdin); //reading one line of stdin

            if (feof(stdin) != 0)
            {
                printf("File processing completed!\n");
                free(line);
                free(countryname);
                free(countrydata);
                return 0;
            }

            switch (line[0]) //finding the right command
            {
                case 'A':
                    if (sscanf(line, "%c %s", &command, countryname) == 2)
                    {
                        add_country(countrydata, countryname, i);
                        i++;
                        countrydata = realloc(countrydata, sizeof(struct Olympia) * (i + 1));
                    }
                    else
                    {
                        printf("Error! Invalid input, try again!");
                    }
                    break;
            case 'Q':
                free(line);
                free(countryname);
                free(countrydata);
                return(EXIT_SUCCESS);

            default:
                printf("Error! Invalid input.\n");              
        }   
    }
}

Ответы [ 2 ]

1 голос
/ 18 апреля 2019

Я думаю, что проблема в

data[i].country = malloc(strlen(str) + 2);  //allocating memory for country name

, который никогда не освобождается.

Чтобы исправить это, измените выражение Q:

case 'Q':
{
    int j;
    for (j = 0; j < i; ++j)
    {
        free(countrydata[i].countryname);
    }
    free(line);
    free(countryname);
    free(countrydata);
    return(EXIT_SUCCESS);    
}

Ноу вашего кода другая проблема:

  • вы не проверяете на *alloc возврат функций,
  • вы используете feof, что контрпродуктивно (тестирование возврата fgetsдостаточно)
  • вы используете динамическую память, где достаточно статического (строка, название страны)
0 голосов
/ 18 апреля 2019

Вы пытаетесь использовать data параметр функции в функции add_country, как если бы это был массив, но вы создаете только одну переменную:

struct Olympia* countrydata = malloc(sizeof(struct Olympia) * 1);

Это создает переменную, а не массив. Попробуйте увеличить число в malloc до sizeof(struct Olimpia) * 10, чтобы получить массив из 10 элементов.

Совет. Читайте о списках.

ОБНОВЛЕНИЕ Пожалуйста, обратите внимание на правильное использование функции realloc - это может вызвать проблемы. realloc функция может вернуть NULL, если не удалось.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...