Memory leak

Память, выделенная динамически не освобожденный

Описание

Этот дефект происходит, когда вы не освобождаете блок от памяти, выделенной через 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 инициализация. Если вы использовали скобки [] чтобы инстанцировать переменной, необходимо вызвать, удаляют со скобками также.

#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;
}

Проверяйте информацию

Группа: Динамическая память
Язык: C | C++
Значение по умолчанию: 'off'
Синтаксис командной строки: MEM_LEAK
Удар: носитель
ID CWE: 401, 404

Введенный в R2013b