ПроблемаУтечка памяти происходит, когда вы не освобождаете блок памяти, выделенный через malloc, calloc, realloc, или new. Если память выделена в функции, дефект не возникает, если:
В рамках функции освобождается память с помощью free или delete.
Функция возвращает указатель, назначенный malloc, calloc, realloc, или new.
Функция сохраняет указатель в глобальной переменной или в параметре.
РискФункции динамического выделения памяти, такие как malloc выделить память в куче. Если вы не освободите память после использования, уменьшите объем памяти, доступной для другого распределения. На встраиваемых системах с ограниченной памятью вы можете исчерпать доступную кучную память даже во время выполнения программы.
ЗафиксироватьОпределите область доступа к динамически выделенной памяти. Освободите блок памяти в конце этой области.
Чтобы освободить блок памяти, используйте free на указателе, который использовался при выделении памяти. Например:
ptr = (int*)malloc(sizeof(int));
...
free(ptr);
Рекомендуется выделять и освобождать память в одном модуле на одном уровне абстракции. Например, в этом примере func выделяет и освобождает память на том же уровне, но func2 не делает.
void func() {
ptr = (int*)malloc(sizeof(int));
{
...
}
free(ptr);
}
void func2() {
{
ptr = (int*)malloc(sizeof(int));
...
}
free(ptr);
} См. раздел
MEM00-C правил CERT-C.
Пример - Динамическая память не освобождается до окончания функции#include<stdlib.h>
#include<stdio.h>
void assign_memory(void)
{
int* pi = (int*)malloc(sizeof(int));
if (pi == NULL)
{
printf("Memory allocation failed");
return;
}
*pi = 42;
/* Defect: pi is not freed */
}В этом примере: pi динамически назначается malloc. Функция assign_memory не освобождает память и не возвращается pi.
Коррекция - свободная память
Одной из возможных корректировок является освобождение памяти, на которую ссылается pi с использованием free функция. free функция должна вызываться перед функцией assign_memory заканчивается
#include<stdlib.h>
#include<stdio.h>
void assign_memory(void)
{
int* pi = (int*)malloc(sizeof(int));
if (pi == NULL)
{
printf("Memory allocation failed");
return;
}
*pi = 42;
/* Fix: Free the pointer pi*/
free(pi);
} Коррекция - возврат указателя из динамического распределения
Другой возможной поправкой является возврат указателя pi. Возвращение pi позволяет функции вызывать assign_memory для освобождения блока памяти с помощью pi.
#include<stdlib.h>
#include<stdio.h>
int* assign_memory(void)
{
int* pi = (int*)malloc(sizeof(int));
if (pi == NULL)
{
printf("Memory allocation failed");
return(pi);
}
*pi = 42;
/* Fix: Return the pointer pi*/
return(pi);
} Пример - Утечка памяти с новым/удалением
#define NULL '\0'
void initialize_arr1(void)
{
int *p_scalar = new int(5);
}
void initialize_arr2(void)
{
int *p_array = new int[5];
}
В этом примере функции создают две переменные: p_scalar и p_array, с использованием new ключевое слово. Однако функции заканчиваются без очистки памяти для этих указателей. Потому что используемые функции new чтобы создать эти переменные, необходимо очистить их память путем вызова delete в конце каждой функции.
Исправление - Добавить удалениеЧтобы исправить эту ошибку, добавьте delete оператор для каждого new инициализация. При использовании скобок [] для создания экземпляра переменной также необходимо вызвать метод delete со скобками.
#define NULL '\0'
void initialize_arrs(void)
{
int *p_scalar = new int(5);
int *p_array = new int[5];
delete p_scalar;
p_scalar = NULL;
delete[] p_array;
p_scalar = NULL;
}