CERT C: Rec. MEM00-C

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

Описание

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

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

Реализация Polyspace

Эта проверка проверяет на наличие следующих проблем:

  • Недопустимое значение без указателя.

  • Отмена присвоения предварительно освобожденного указателя.

  • Использование ранее освобожденного указателя.

Примеры

расширить все

Проблема

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

Риск

The 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. Перед освобождением указателей проверьте их на значения 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. Перед удалением указателей проверьте их на значения 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;
   }

The free оператор освобождает блок памяти, который pi относится к. Поэтому разыменование pi после 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;
}

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

Группа: Рек. 08. Управление памятью (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 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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