Освобождение памяти и предотвращение утечек
Корректно освобождайте ресурсы.
«Освобождение памяти и предотвращение утечек» — бесплатный урок C Academy на CoddyKit. Это урок 4 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C Academy содержит 4 уроков всего.
Каждому malloc нужен free
Память в куче остаётся занятой, пока Вы не освободите её с помощью free. Если потерять единственный указатель на блок, не освободив его, эта память станет утечкой.
Со временем утечки накапливаются и могут исчерпать память в долго работающих программах.
int *a = malloc(100 * sizeof(*a));
/* ... use a ... */
free(a);Что на самом деле делает free
free(p) возвращает блок распределителю памяти, чтобы его можно было использовать повторно. Значение самого p при этом не изменяется.
После вызова free p по-прежнему указывает на старый адрес, который теперь недействителен. Обращение к нему приводит к неопределённому поведению.
free(p);
/* p is now a dangling pointer */Опасность висячего указателя
Использование указателя после освобождения памяти — это ошибка использования после освобождения. Иногда она кажется безобидной, но затем может повредить данные или вызвать непредсказуемое падение программы.
Простая мера защиты — сразу после освобождения установить указатель в NULL.
free(a);
a = NULL; /* now misuse is a clean NULL deref, easier to catch */Двойное освобождение — неопределённое поведение
Двойной вызов free для одного блока повреждает внутреннее состояние распределителя памяти и часто приводит к сбою.
Установка указателя в NULL после первого освобождения помогает, поскольку free(NULL) явно считается безопасным и ничего не делает.
free(a);
a = NULL;
free(a); /* free(NULL) is a harmless no-op */Освобождайте только память, выделенную через malloc
Передавайте в free только указатель, полученный из malloc, calloc или realloc.
Освобождение адреса переменной в стеке, строкового литерала или указателя на середину блока приводит к неопределённому поведению.
int x = 5;
/* free(&x); WRONG: x is on the stack */
int *p = malloc(sizeof(int));
free(p); /* correct */Утечка из-за раннего возврата
Распространённая причина утечки: программа выделяет память, затем попадает в ветку обработки ошибки и возвращает управление, не освободив её. Блок теряется.
Убедитесь, что каждый путь выхода, отвечающий за эту память, сначала освобождает её.
int *a = malloc(n * sizeof(*a));
if (something_failed) {
free(a); /* don't forget this before returning */
return -1;
}Программа с корректным выделением и освобождением памяти
Эта программа выделяет, использует и освобождает память на каждом пути выполнения, не оставляя утечек.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n = 4;
int *a = malloc(n * sizeof(*a));
if (!a) return 1;
for (int i = 0; i < n; i++) a[i] = i + 1;
int sum = 0;
for (int i = 0; i < n; i++) sum += a[i];
printf("%d\n", sum);
free(a);
a = NULL;
return 0;
}Освобождение вложенных выделений
Если блок содержит указатели на другие блоки, сначала освободите внутренние блоки, а затем внешний.
Освобождение внешнего блока первым приведёт к потере адресов внутренних блоков и утечке памяти.
for (size_t i = 0; i < rows; i++)
free(grid[i]); /* free each row first */
free(grid); /* then the array of pointers */Один владелец для каждого блока
Определите, какая часть кода владеет каждым выделенным блоком и отвечает за его освобождение.
Если два указателя ссылаются на один блок и оба освобождают его, возникает двойное освобождение. Чётко определённое владение предотвращает эту проблему.
Обнаружение утечек с помощью инструментов
Вам не нужно искать утечки вручную. Такие инструменты, как valgrind или AddressSanitizer, сообщают об утечках и недопустимых освобождениях, указывая номера строк.
Скомпилируйте программу с помощью -g и запустите её под управлением инструмента, чтобы точно узнать, что не было освобождено.
/* gcc -g -fsanitize=address prog.c && ./a.out */
/* or: valgrind --leak-check=full ./a.out */Освобождайте ресурсы в обратном порядке подготовки
Надёжное правило: если функция получает несколько ресурсов, освобождайте их в обратном порядке.
Это отражает порядок построения зависимостей и делает очистку предсказуемой.
char *buf = malloc(64);
int *idx = malloc(64 * sizeof(int));
/* ... use them ... */
free(idx); /* free last-acquired first */
free(buf);Быстрая проверка
Проверьте, насколько хорошо Вы поняли освобождение памяти.
Повторение
Для каждого выделения памяти должен быть ровно один вызов free на каждом возможном пути выполнения.
Избегайте висячих указателей и двойного освобождения, устанавливая указатели в NULL после освобождения. Освобождайте вложенные блоки изнутри наружу, назначайте каждому блоку одного владельца и используйте valgrind или санитизатор адресов для обнаружения утечек. Теперь у Вас есть полный набор инструментов для работы с динамическими массивами.
Изучай C с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 39
- Уроки
- 144
Часто задаваемые вопросы
Урок «Освобождение памяти и предотвращение утечек» бесплатный?
Да — полный текст урока «Освобождение памяти и предотвращение утечек» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C Academy, подпишись на CoddyKit PRO. Курс C Academy содержит 4 уроков всего.
Чему я научусь в уроке «Освобождение памяти и предотвращение утечек»?
Корректно освобождайте ресурсы. Ты практикуешь C Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C Academy?
Предыдущий опыт не требуется. C Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 4 из 4.
Сколько времени занимает урок «Освобождение памяти и предотвращение утечек»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C Academy?
Да. Каждый урок C Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Выделение массива
- Изменение размера с realloc
- Многоразовый тип вектора
- Освобождение памяти и предотвращение утечек