Когда и зачем использовать malloc? - PullRequest
44 голосов
/ 10 января 2012

Ну, я не могу понять, когда и почему это необходимо для выделения памяти, используя malloc.

Вот мой код:

#include <stdlib.h>

int main(int argc, const char *argv[]) {

  typedef struct {
    char *name;
    char *sex;
    int age;
  } student;


  //Now I can do two things
  student p;

  //or
  student *ptr = (student *)malloc(sizeof(student));

  return 0;
}

Почему это необходимо для выделенияпамять, когда я могу просто использовать student p;?

Ответы [ 6 ]

43 голосов
/ 10 января 2012

malloc используется для динамического выделения памяти. Как уже говорилось, это динамическое распределение, которое означает, что вы выделяете память во время выполнения. Например, когда вы не знаете объем памяти во время компиляции.

Один пример должен прояснить это. Скажем, вы знаете, что будет максимум 20 студентов. Таким образом, вы можете создать массив со статическими 20 элементами. Ваш массив сможет вместить максимум 20 студентов. Но что, если вы не знаете количество студентов? Скажем, первым вводом является количество студентов. Это может быть 10, 20, 50 или что-то еще. Теперь вы возьмете n = число студентов во время выполнения и выделите столько памяти динамически, используя malloc.

Это только один пример. Во многих ситуациях, подобных этой, требуется динамическое распределение.

Взгляните на справочную страницу malloc (3) .

21 голосов
/ 10 января 2012

Вы используете malloc, когда вам нужно выделить объекты, которые должны существовать после срока действия текущего блока (где копирование при возврате также будет дорого), или если вам нужно выделить больше памяти, чемразмер этого стека (то есть: массив из 3 МБ локального стека - это плохая идея).

До того, как C99 представил VLA, вам также потребовалось , чтобы выполнить выделениединамический размерный массив, однако, он необходим для создания динамических структур данных, таких как деревья, списки и очереди, которые используются многими системами.Есть, вероятно, еще много причин, это всего лишь несколько.

17 голосов
/ 28 ноября 2012

Немного расширив структуру примера, рассмотрим следующее:

#include <stdio.h>

int main(int argc, const char *argv[]) {

typedef struct {
 char* name;
 char* sex;
 char* insurace;
 int age;
 int yearInSchool;
 float tuitionDue;
}student;


//Now I can do two things
student p;

//or
student *p = (student *)malloc(sizeof(student));

return 0
}

C a - это язык, который неявно передается по значению, а не по ссылке.В этом примере, если мы передадим 'p' функции, чтобы выполнить некоторую работу над ней, мы создадим копию всей структуры.При этом используется дополнительная память (общее количество места, которое потребуется конкретной структуре), она медленнее и потенциально плохо масштабируется (подробнее об этом за минуту).Однако, передавая * p, мы не передаем всю структуру.Мы только передаем в памяти адрес, который ссылается на эту структуру.Количество передаваемых данных меньше (размер указателя), поэтому операция выполняется быстрее.

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

4 голосов
/ 10 января 2012

malloc = ALLOCation в памяти.

Если вы работали с другими языками программирования, вы могли бы использовать ключевое слово 'new'.

Malloc делает то же самое в C. Это занимаетпараметр, какой объем памяти должен быть выделен, и он возвращает переменную-указатель, которая указывает на первый блок памяти из всего блока памяти

, который вы создали в памяти.Пример -

int *p = malloc(sizeof(int)*10);

Теперь * p будет указывать на первый блок последовательного 20 целочисленного блока, зарезервированного в памяти.

Вы можете проходить через каждый блок, используя ++ и -оператор.Всего наилучшего.

0 голосов
/ 30 декабря 2018

Давайте попробуем решить этот вопрос с учетом различных аспектов

размер

malloc позволяет вам выделять гораздо большие области памяти, чем те, которые выделяются просто с помощью student p; или int x[n];. Причина в том, что malloc выделяет пространство в куче, а другой выделяет его в стеке

Язык программирования C управляет памятью статически, автоматически или динамически. Переменные статической длительности размещаются в основной памяти, обычно вместе с исполняемым кодом программы, и сохраняются в течение всего срока действия программы; Переменные автоматической длительности размещаются в стеке и приходят и уходят при вызове и возвращении функций. Для переменных статической длительности и автоматической длительности размер выделения должен быть постоянным времени компиляции (за исключением случая автоматических массивов переменной длины [5]). Если требуемый размер неизвестен до времени выполнения (например, если данные произвольного размера читаются пользователем или из файла на диске), то использование объектов данных фиксированного размера не подходит. ( из Википедии )

Область

Обычно объявленные переменные удаляются / освобождаются после блока, в котором они объявлены (они объявляются в стеке). С другой стороны, переменные с памятью, выделенной с помощью malloc, остаются до тех пор, пока они не будут освобождены вручную.

Это также означает, что вы не можете создать переменную / массив / структуру в функции и вернуть ее адрес (так как память, на которую она указывает, может быть освобождена). Компилятор также пытается предупредить вас об этом, выдав предупреждение:

Предупреждение - адрес стековой памяти, связанной с локальной переменной 'совпадения', возвращается

Подробнее читать

Изменение размера (realloc)

Как вы уже догадались, это невозможно обычным способом

Обнаружение ошибок

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

Внесение изменений в строковое содержимое в будущем

Если вы создаете в памяти строку типа char *some_memory = "Hello World";, вы не можете сделать some_memory[0] = 'h';, поскольку она хранится как строковая константа, а память, в которой она хранится, доступна только для чтения. Если вместо этого вы используете malloc, вы можете изменить содержимое позже. Для получения дополнительной информации проверьте этот ответ

Для получения более подробной информации о массивах переменного размера посмотрите на это

0 голосов
/ 10 января 2012

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

...