CERT C: Rec. MEM00-C

Выделите и освободите память в том же модуле на том же уровне абстракции

Описание

Управляйте определением

Выделите и освободите память в том же модуле на том же уровне абстракции. [1]

Примеры

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

Описание

Недопустимый свободный от указателя происходит, когда блок памяти выпущенное использование функции free не был ранее выделен с помощью malloc, calloc или realloc.

Риск

Функция free выпускает блок памяти, выделенной на куче. При попытке получить доступ к местоположению на куче, которую вы не выделили ранее, отказ сегментации может произойти.

Проблема может подсветить ошибки кодирования. Например, вы, возможно, хотели использовать функцию free или предыдущую функцию malloc на различном указателе.

Фиксация

В большинстве случаев можно устранить проблему путем удаления оператора free. Если указатель не является выделенной памятью от кучи с malloc или calloc, вы не должны освобождать указатель. Можно просто снова использовать указатель как требуется.

Если проблема подсвечивает ошибку кодирования, такую как использование free или malloc на неправильном указателе, исправьте ошибку.

Если проблема происходит, потому что вы используете функцию free, чтобы освободить память выделенный с оператором new, заменяете функцию free на оператор delete.

Пример - недопустимый свободный от ошибки указателя

#include <stdlib.h>

void Assign_Ones(void) 
{
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1; 
 
  free(p);   
  /* Defect: p does not point to dynamically allocated memory */
}

Указатель p освобожден с помощью функции free. Однако p указывает на ячейку памяти, которая не была динамически выделена.

Исправление — удаляет освобождение указателя

Если число элементов массива, p известен во время компиляции, одно возможное исправление, должно удалить освобождение указателя p.

#include <stdlib.h>

void Assign_Ones(void)
 {
  int p[10];
  for(int i=0;i<10;i++)
     *(p+i)=1;   
  /* Fix: Remove deallocation of p */
 }

Исправление — вводит выделение указателя

Если число элементов массива, p не известен во время компиляции, одно возможное исправление, должно динамически выделить память массиву p.

#include <stdlib.h>

void Assign_Ones(int num) 
{
  int *p;
  /* Fix: Allocate memory dynamically to p */
  p=(int*) calloc(10,sizeof(int)); 
  for(int i=0;i<10;i++)
     *(p+i)=1; 
  free(p); 
}

Описание

Освобождение ранее освобожденного указателя происходит, когда блок памяти освобожден несколько раз с помощью функции free без промежуточного выделения.

Риск

Когда указатель является выделенной динамической памятью с malloc, calloc или realloc, это указывает на ячейку памяти на куче. Когда вы используете функцию free на этом указателе, связанный блок памяти освобожден для перераспределения. Попытка освободить этот блок от памяти может привести к отказу сегментации.

Фиксация

Фиксация зависит от первопричины дефекта. Смотрите, намеревались ли вы выделить блок памяти указателю между первым освобождением и вторым. В противном случае удалите второй оператор free.

Как хорошая практика, после того, как вы освободите блок памяти, присваивают соответствующий указатель на NULL. Прежде, чем освободить указатели, проверяйте их на Нулевые значения и обработайте ошибку. Таким образом вы защищены от освобождения уже освобожденного блока.

Пример - освобождение ранее освобожденной ошибки указателя

#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    free (pi);       
    /* Defect: pi has already been freed */
}

Первый оператор free выпускает блок памяти, к которой относится pi. Второй оператор free на pi выпускает блок памяти, которая уже была освобождена.

Исправление — удаляет дублирующееся освобождение

Одно возможное исправление должно удалить второй оператор free.

#include <stdlib.h>

void allocate_and_free(void)
{

    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return;

    *pi = 2;
    free(pi);
    /* Fix: remove second deallocation */
 }

Описание

Использование ранее освобожденного указателя происходит, когда вы получаете доступ к блоку памяти после освобождения блока с помощью функции free.

Риск

Когда указатель является выделенной динамической памятью с malloc, calloc или realloc, это указывает на ячейку памяти на куче. Когда вы используете функцию free на этом указателе, связанный блок памяти освобожден для перераспределения. Попытка получить доступ к этому блоку памяти может привести к непредсказуемому поведению или даже отказу сегментации.

Фиксация

Фиксация зависит от первопричины дефекта. Смотрите, намеревались ли вы освободить память позже или выделить другой блок памяти указателю перед доступом.

Как хорошая практика, после того, как вы освободите блок памяти, присваивают соответствующий указатель на NULL. Прежде, чем разыменовать указатели, проверяйте их на Нулевые значения и обработайте ошибку. Таким образом вы защищены от доступа к освобожденному блоку.

Пример - использование ранее освобожденной ошибки указателя

#include <stdlib.h>
#include <stdio.h>
 int increment_content_of_address(int base_val, int shift)
   { 
    int j;
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return 0;

    *pi = base_val;
    free(pi);

    j = *pi + shift;
    /* Defect: Reading a freed pointer */
 
    return j;
   }

Оператор free выпускает блок памяти, к которой относится pi. Поэтому dereferencingpi после оператора free не допустим.

Исправление — свободный указатель после использования

Одно возможное исправление должно освободить указатель pi только после последнего экземпляра, где к этому получают доступ.

#include <stdlib.h>

int increment_content_of_address(int base_val, int shift)
{
    int j;
    int* pi = (int*)malloc(sizeof(int));
    if (pi == NULL) return 0;

    *pi = base_val;

    j = *pi + shift;
    *pi = 0;

    /* Fix: The pointer is freed after its last use */
    free(pi);               
    return j;
}

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

Группа: Rec. 08. Управление памятью (MEM)

Введенный в R2019a


[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

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

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.