Как освободить () массив структур, выделенных mallo c ()? - PullRequest
3 голосов
/ 17 февраля 2020

Я работал над проектом, который использует структуры в качестве хранилища для строк. Я объявил, что структура состоит из членов типа char:

struct datastore1
{
    char name[50];
    char address[50];
    char email[50];
    char number[50];
    char idnum[50];
};

Я знаю, что могу просто сделать char *name, char *address..., но допустим, мы указали его с максимальной длиной 50. Затем в моей функции, которая использует struct, я mallo c 'редактировал его с размером индекса 30:

struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));

Предположительно, я закончил копировать все строки в структуру, получив доступ к каждому индексу, Как я должен освободить выделенную память, которая использовалась после зовет Малло c? Я пытался сделать free(dsdata) в конце программы, но я не уверен, что это правильный путь. Должен ли я освободить каждый индекс в отдельности? Пожалуйста, просветите меня. Заранее спасибо за отзыв!

Ответы [ 4 ]

2 голосов
/ 17 февраля 2020

Как освободить выделенную память, которая использовалась после вызова mallo c?

Рассмотрим пример ниже,

struct datastore1 *obj1 = malloc(sizeof(struct datastore1));
free(obj1);

Здесь obj1 - это указывая на блок памяти размером, равным datastore1, для освобождения необходимо отправить адрес, который выделен malloc.

enter image description here

также

struct datastore1 *obj2 = malloc(3 * sizeof(struct datastore1));
free(obj2);

obj2 указывает на блок непрерывной памяти размером 3 * sizeof(datastore1), вам нужно передать базовый адрес в free

enter image description here

Должен ли я освобождать каждый индекс по отдельности?

НЕТ, поскольку блок памяти выделяется только один раз, и вам нужно free точно один раз.

Позвольте мне расширить его,

struct datastore1 *obj3[3];
for(int i=0;i<3;i++)
   obj3[i] = malloc(sizeof(struct datastore1));

for(int i=0;i<3;i++)
    free(obj3[i]);

Здесь obj3 - массив указателей, и каждый индекс указывает на различную часть памяти и, следовательно, должен быть освобожден индивидуально.

enter image description here


Примечание. Для простоты я не рассматривал возвращаемое значение из malloc. Нулевая проверка должна быть сделана для malloc возвращаемого значения.

1 голос
/ 17 февраля 2020

1.

Как освободить выделенную память, которая использовалась после вызова mallo c?

Я пытался сделать free(dsdata) в конце программы, но я не уверен, что это правильный путь.

free(dsdata) нормально, с Вы выделили все пространство одним вызовом malloc с:

struct datastore1 *dsdata = malloc(30 * sizeof(struct datastore1));

Чтобы процитировать стандарт (C18), 7.22.3.4 - «Функция mallo c» (подчеркните мою):

7.22.3.4 Функция Малло c

Сводка

1

 #include <stdlib.h>
 void* malloc(size_t size);

Описание

2 The mallo c функция выделяет пространство для объекта, размер которого определяется размером и значение которого не определено.

Возвращает

3 Функция mallo c возвращает либо пустой указатель или указатель на выделенное пространство .

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

Функция free() «знает», что dsdata является ссылкой на все выделенное пространство. Вам не нужно отдельно освобождать каждую из 30 структур типа struct datastore1 в памяти.


2.

Должен ли я освобождать каждый индекс по отдельности?

Нет, вам не нужно, и, что еще важнее, вы не должны делать это; это будет Неопределенное поведение :

Цитирование из текущего стандарта (C18), 7.22.3.5/3 - «Свободная функция» (выделите мое):

В противном случае, если аргумент не соответствует указателю, ранее возвращенному функцией управления памятью , или если пространство было освобождено при вызове free или reallo c, поведение не определено.

0 голосов
/ 17 февраля 2020

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

valgrind -v --leak-check=full --track-origins=yes ./your-program

Это выполнит вашу программу на виртуальном процессоре valgrind и предоставит вам полную информацию об используемых ресурсах.

В основном оператор [] в C языке программирования в контексте определения массива вызывает создание (скажем, для упрощения) stati c массив - это означает, что массив включается в размер структуры (если он определен как часть структуры) или хранится в стеке (если он определен в функции или глобально).
Функция malloc возвращает адрес блока данных, который вы можете использовать. Размер этого блока по крайней мере такой же большой, как вы просили. Когда вы используете free, вы освобождаете этот блок, что в этом случае означает, что все данные в блоке, указанном по этому адресу, будут освобождены.

0 голосов
/ 17 февраля 2020

Насколько я понимаю, вы использовали malloc только для выделения пространства для массива datastore1 struct, поэтому достаточно просто сделать free(dsdata).

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

...