exponenta event banner

ISO/IEC TS 17961 [uninitref]

Ссылка на неинициализированную память

Описание

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

Ссылка на неинициализированную память. [1 ]

Внедрение Polyspace

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

  • Неинициализированный указатель.

  • Указатель на неинициализированное значение преобразован в указатель const.

  • Неинициализированная переменная.

Примеры

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

Проблема

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

Риск

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

Зафиксировать

Исправление зависит от первопричины дефекта. Например, вы назначили адрес указателю, но назначение недоступно.

Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.

См. примеры исправлений ниже. Рекомендуется инициализировать указатель на значение NULL при объявлении указателя.

Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.

Пример - Неинициализированная ошибка указателя
#include <stdlib.h>

int* assign_pointer(int* prev)
{
    int j = 42;
    int* pi;

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

    *pi = j;                    
    /* Defect: Writing to uninitialized pointer */

    return pi;
}

Если prev не является NULL, указатель pi не назначен адрес. Однако pi обнуляется на всех путях выполнения, независимо от того, prev является NULL или нет.

Исправление - инициализация указателя на каждом пути выполнения

Одной из возможных корректировок является присвоение адреса pi когда prev не является NULL.

#include <stdlib.h>

int* assign_pointer(int* prev)
{
    int j = 42;
    int* pi;

    if (prev == NULL) 
       {
        pi = (int*)malloc(sizeof(int));
        if (pi == NULL) return NULL;
       } 
    /* Fix: Initialize pi in branches of if statement  */
    else 
        pi = prev;              
    

    *pi = j;

    return pi;
}
Проблема

Указатель на неинициализированное значение, преобразованное в указатель const, возникает, когда указатель на константу (const int*, const char*и т.д.) назначается адрес, который еще не содержит значения.

Риск

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

Зафиксировать

Инициализируйте переменную перед назначением ее адреса указателю на константу.

Пример - Указатель на неинициализированное значение преобразован в ошибку указателя const
#include<stdio.h>

void Display_Parity()
 {
  int num,parity;
  const int* num_ptr = &num;  
  /* Defect: Address &num does not store a value */

  printf("Enter a number\n:");
  scanf("%d",&num);

  parity=((*num_ptr)%2);
  if(parity==0)
    printf("The number is even.");
  else
    printf("The number is odd.");

 }

num_ptr объявляется как указатель на константу. Однако переменная num не содержит значения, когда num_ptr назначается адрес &num.

Исправление - сохранение значения в адресе перед присвоением указателю

Одной из возможных корректировок является получение значения num от пользователя до &num присвоен num_ptr.

#include<stdio.h>

void Display_Parity()
 {
  int num,parity;
  const int* num_ptr;

  printf("Enter a number\n:");
  scanf("%d",&num);

 /* Fix: Assign &num to pointer after it receives a value */ 
  num_ptr=&num;                     
  parity=((*num_ptr)%2);
  if(parity==0)
    printf("The number is even.");
  else
    printf("The number is odd.");
 }

scanf инструкция сохраняет значение в &num. После сохранения значения его можно присвоить &num кому num_ptr.

Проблема

Неинициализированная переменная возникает, когда переменная не инициализируется до считывания ее значения.

Риск

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

Зафиксировать

Исправление зависит от первопричины дефекта. Например, вы назначили значение переменной, но назначение недоступно, или вы назначили значение переменной в одной из двух ветвей условного оператора. Исправьте недоступный код или отсутствующее назначение.

Часто детали результата показывают последовательность событий, которые привели к дефекту. Исправление может быть реализовано для любого события в последовательности. Если сведения о результатах не отображают историю событий, можно выполнить обратную трассировку, щелкнув правой кнопкой мыши параметры в исходном коде и просмотреть предыдущие связанные события. См. также раздел Интерпретация результатов поиска ошибок в интерфейсе пользователя Polyspace Desktop.

См. примеры исправлений ниже. Рекомендуется инициализировать переменную при объявлении.

Если вы не хотите устранять проблему, добавьте комментарии к результату или коду, чтобы избежать другой проверки. См. раздел Результаты анализа пространства адресов с помощью исправлений ошибок или обоснований.

Пример - Ошибка неинициализированной переменной
int get_sensor_value(void)
{
    extern int getsensor(void);
    int command;
    int val;

    command = getsensor();
    if (command == 2) 
      {
        val = getsensor();
      }

    return val;              
    /* Defect: val does not have a value if command is not 2 */
}

Если command не равно 2, переменная val не назначен. В этом случае возвращаемое значение функции get_sensor_value не определен.

Исправление - инициализация во время объявления

Одной из возможных корректировок является инициализация val во время объявления, чтобы инициализация не обходилась по некоторым путям выполнения.

int get_sensor_value(void)
{
    extern int getsensor(void);
    int command;
    /* Fix: Initialize val */
    int val=0;

    command = getsensor();
    if (command == 2) 
      {
        val = getsensor();
      }

    return val;              
 }

val присваивается начальное значение 0. Когда command не равно 2, функция get_sensor_value возвращает это значение.

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

Разрешимость: неразрешимая
Представлен в R2019a

[1] Выдержки из стандарта «ISO/IEC TS 17961 Technical Specification - 2013-11-15» воспроизводятся с согласия AFNOR. Нормативную ценность имеет только оригинальный и полный текст стандарта, опубликованный изданиями AFNOR - доступный через веб-сайт www.boutique.afnor.org.