ПроблемаУтечка памяти происходит, когда вы не освобождаете блок памяти, выделенный через 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);
}
См. Раздел «Правила
CERT-C MEM00-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
функция. The 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
инициализация. Если вы использовали скобки []
чтобы создать экземпляр переменной, необходимо также вызвать удаление с помощью скобок.
#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;
}