Malloc и free в C: выделение и освобождение памяти
💻 Информатика · 10 класс
Это функции библиотеки, а не сами системные вызовы: проверка NULL, размер блока и срок жизни указателя.

Что делают функции
Malloc выделяет блок памяти заданного размера в байтах и возвращает указатель на него либо нулевой указатель при неудаче. Free освобождает ранее выделенный блок. Обе функции объявлены в stdlib.h. Называть их непосредственно системными вызовами неточно: это интерфейс стандартной библиотеки C; способ взаимодействия с операционной системой зависит от реализации.
Выделенная память не получает автоматически нулевые значения. Сначала проверьте результат, затем запишите элементы, и только после этого читайте их. Освобождение должно происходить после последнего необходимого обращения к блоку.
Рабочий пример
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t count = 3;
int *values = malloc(count * sizeof *values);
if (values == NULL) {
return EXIT_FAILURE;
}
for (size_t i = 0; i < count; ++i) {
values[i] = (int)(i + 1) * 10;
}
printf("%d\n", values[2]);
free(values);
values = NULL;
return EXIT_SUCCESS;
}Результат — 30. Выражение sizeof *values вычисляет размер одного элемента нужного типа; оно не читает ещё не созданный элемент. В C результат malloc не требует приведения к int*. Это не тот же интерфейс, что оператор new в C++.
Размер и границы
Блок рассчитан на три элемента, поэтому допустимые индексы — 0, 1, 2. Запись values[3] выходит за границы, хотя память физически может выглядеть доступной. Поведение такой программы не определено стандартом.
При большом количестве элементов нужно отдельно исключать переполнение произведения count на размер элемента. Если count приходит от пользователя, проверяют допустимый диапазон до malloc; маленькая константа 3 в примере намеренно убирает эту отдельную задачу.
Что меняется после free
После освобождения нельзя читать или записывать прежний блок через values либо его копии. Само free не устанавливает переменную-указатель в NULL. Поэтому пример делает это отдельным присваиванием. Но обнуление одного указателя не исправляет все остальные сохранённые копии адреса.
Повторный free для того же освобождённого блока недопустим. Вызов free(NULL), напротив, разрешён и ничего не делает. Нельзя освобождать адрес обычной локальной переменной или указатель на середину выделенного блока: передают исходный допустимый адрес от функций управления памятью.
Разобранная ошибка
Если перед проверкой NULL сразу написать values[0] = 10, программа при неудаче выделения обратится через нулевой указатель. Проверка должна предшествовать любому такому обращению. Если же потерять адрес блока без free, возникнет утечка памяти.
Практика
- Какой индекс последнего элемента в блоке из трёх int?
- Гарантирует ли malloc нули в элементах?
- Безопасно ли после free(values) читать values[0]?
Ответы
1. 2, индексация начинается с нуля. 2. Нет: значения до инициализации неопределённые; сначала их записывают. 3. Нет: срок жизни блока закончился. Сохранённый адрес не даёт права пользоваться освобождённой памятью, даже если при пробном запуске программа не упала.