exponenta event banner

Просмотр и исправление незаконных проверок указателей

Выполните один или несколько из этих шагов до тех пор, пока не будет определено исправление для проверки Незаконно отключенных указателей. Существует несколько способов исправления этой проверки. Описание проверки и примеры кода см. в разделе Illegally dereferenced pointer.

Иногда, особенно для оранжевой проверки, можно определить, что проверка представляет собой не реальную ошибку, а предположение Polyspace ®, которое не соответствует вашему коду. Если для смягчения предположения можно использовать опцию анализа, повторно запустите проверку с помощью этой опции. В противном случае в результат или код можно добавить комментарий и обоснование.

Общий рабочий процесс, применяемый ко всем проверкам, см. в разделе Интерпретация результатов проверки кода в пользовательском интерфейсе Polyspace Desktop.

Шаг 1: Интерпретировать информацию о проверке

Установите курсор на операторе отмены привязки.

Получите из подсказки следующую информацию:

  • Может ли указатель быть NULL.

    В следующем примере: ptr может быть NULL при обособлении.

    Возможное исправление: Dereference ptr только если это не так NULL.

    if(ptr !=NULL)
        *ptr = 1;
    else 
        /* Alternate action */

  • Указывает ли указатель на динамически выделенную память.

    В следующем примере: ptr может указывать на динамически выделяемую память. Возможно, что возвращается оператор динамического выделения памяти NULL.

    Возможное исправление: Проверьте возвращаемое значение оператора выделения памяти для NULL.

    ptr = (char*) malloc(i);
    if(ptr==NULL)
      /* Error handling*/
    else {
      .
    	.
    	*ptr=0;
    	.
    	.
    }

  • Указывает ли указатель за пределами допустимых границ. Указатель указывает на внешние границы, когда сумма размера и смещения указателя больше размера буфера.

    В следующем примере размер смещения (4096 байт) вместе с размером указателя (4 байта) больше размера буфера (4096 байт). Если указатель указывает на массив:

    • Размер буфера - это размер массива.

    • Смещение - это разность между началом массива и текущим расположением указателя.

    Возможное исправление: Узнайте, почему указатель указывает за пределы допустимого буфера.

  • Может ли указатель указывать за пределами допустимых границ, поскольку размер буфера неизвестен.

    В следующем примере размер буфера неизвестен.

    Возможное исправление: Проверьте, назначен ли указатель:

    • Возвращаемое значение неопределенной функции.

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

    • Другой указатель другого типа, например, void*.

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

    В следующем примере программное обеспечение идентифицирует упрямую функцию, getAddress, в качестве вероятной причины.

    Возможное исправление: Чтобы избежать несанкционированного удаления указателя, ограничьте возвращаемое значение getAddress. Например, укажите, что getAddress возвращает указатель на 10-элементный массив. Дополнительные сведения см. в разделе Допущения о упорных функциях.

Шаг 2: Определение первопричины проверки

Выберите чек и запишите информацию на панели Сведения о результате (Result Details).

  • Если на панели Сведения о результате (Result Details) отображается последовательность инструкций, которые приводят к проверке, выберите каждую инструкцию и выполните трассировку до основной причины.

  • Если на панели Сведения о результате (Result Details) отображается номер строки вероятной причины проверки, в интерфейсе пользователя Polyspace щелкните правой кнопкой мыши панель Источник (Source). Выберите «Перейти к строке».

  • В противном случае, основываясь на характере ошибки, используйте один из следующих методов для поиска первопричины. В интерфейсе пользователя Polyspace можно выполнить только следующие действия.

    ОшибкаКак найти первопричину
    Указатель может быть NULL.

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

    1. Щелкните указатель правой кнопкой мыши и выберите Поиск всех привязок (Search For All References).

    2. Найдите каждый предыдущий экземпляр, где указателю назначен адрес.

    3. Для каждого экземпляра на панели «Источник» установите курсор на указатель. Подсказка указывает, может ли указатель быть NULL.

      Возможное исправление: Если указатель может быть NULL, разместите чек для NULL сразу после назначения.

      if(ptr==NULL)
        /* Error handling*/
      else {
        .
        .
      	}
    4. Если указатель отсутствует NULL, проверьте, происходит ли назначение только в ветви условного оператора. Исследовать, когда эта ветвь не выполняется.

      Возможное исправление: назначьте допустимый адрес указателю во всех ветвях условного оператора.

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

    Определите место назначения.

    1. Щелкните указатель правой кнопкой мыши и выберите Поиск всех привязок (Search For All References).

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

      Возможное исправление: После выделения проверьте указатель на NULL.

    Указатель может указывать внешние границы, разрешенные буфером.

    1. Найдите разрешенный буфер.

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

      2. Поиск определения переменной. Обычно это первый результат поиска.

        Если переменная является массивом, запишите размер массива. Если переменная является структурой, выполните поиск имени типа структуры на вкладке Поиск (Search) и найдите определение структуры. Обратите внимание на размер поля структуры, на которое указывает указатель.

    2. Узнайте, почему указатель указывает за пределы допустимого буфера.

      1. Щелкните указатель правой кнопкой мыши и выберите Поиск всех привязок (Search For All References).

      2. Определите любое приращение или уменьшение указателя. Проверьте, хотите ли вы сделать приращение или уменьшение.

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

Шаг 3: Поиск общих причин проверки

Найдите общие причины проверки указателя «Незаконно».

  • Если для перемещения по массиву используются указатели, проверьте, можно ли использовать вместо этого индекс массива.

    Чтобы избежать использования в коде арифметики указателей, найдите нарушения правила MISRA C ®: 2004 17.4 или MISRA C: 2012 18.4. Дополнительные сведения см. в разделе Проверка нарушений стандартов кодирования.

  • Проверьте, используются ли указатели для перемещения по полям структуры.

    Полиспейс не позволяет указателю на одно поле структуры указывать на другое поле. Чтобы разрешить такое поведение, используйте параметр Enable pointer arithmetic across fields (-allow-ptr-arith-on-struct).

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

    Polyspace не допускает такой отмены. Чтобы разрешить такое поведение, используйте параметр Allow incomplete or partial allocation of structures (-size-in-bytes).

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

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

  • Проверьте, выполняется ли приведение между двумя указателями несовместимых размеров.

Шаг 4: Проверка трассировки в соответствии с предположением Polyspace

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

Например, указатель получает адрес от неопределенной функции. Затем:

  1. Polyspace предполагает, что функция может вернуться NULL.

    Поэтому смещение указателя оранжевое.

  2. Polyspace также предполагает допустимый размер буфера в зависимости от типа указателя.

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

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

Дополнительные сведения см. в разделе Допущения анализа проверки кода.

Примечание

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