exponenta event banner

CERT C++: MEM31-C

Освободить динамически выделяемую память, если она больше не требуется

Описание

Определение правила

Освободить динамически выделяемую память, если она больше не требуется. [1 ]

Внедрение Polyspace

Эта проверка проверяет утечку памяти.

Примеры

развернуть все

Проблема

Утечка памяти происходит, когда вы не освобождаете блок памяти, выделенный через 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;
}

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

Группа: 06. Управление памятью (MEM)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ МЕЛЛОНА И/ИЛИ ЕГО ПРОГРАММНОГО ИНЖЕНЕРНОГО ИНСТИТУТА, СОДЕРЖАЩИЙСЯ В НАСТОЯЩЕМ ДОКУМЕНТЕ, ПОСТАВЛЯЕТСЯ КАК ЕСТЬ. УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ, ВЫРАЖЕННЫХ ИЛИ ПОДРАЗУМЕВАЕМЫХ, В ОТНОШЕНИИ ЛЮБЫХ ВОПРОСОВ, ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИВАЯСЬ, ГАРАНТИИ ПРИГОДНОСТИ ДЛЯ ЦЕЛЕЙ ИЛИ ТОВАРНОЙ ПРИГОДНОСТИ, ИСКЛЮЧИТЕЛЬНОСТИ ИЛИ РЕЗУЛЬТАТОВ, ПОЛУЧЕННЫХ ОТ ИСПОЛЬЗОВАНИЯ УНИВЕРСИТЕТ КАРНЕГИ МЕЛЛОН НЕ ДАЕТ НИКАКИХ ГАРАНТИЙ В ОТНОШЕНИИ СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКИХ ПРАВ.

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.