CERT C: Rec. FLP03-C

Обнаружьте и обработайте ошибки с плавающей точкой

Описание

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

Обнаружьте и обработайте ошибки с плавающей точкой. [1]

Примеры

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

Описание

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

Точное выделение ресурсов хранения для различных типов с плавающей точкой зависит от вашего процессора. Смотрите Target processor type (-target).

Риск

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

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Используйте этот список событий, чтобы определить, как преобразовываемая переменная получает свое текущее значение, можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.

Можно зафиксировать дефект:

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

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

В целом избегайте преобразований в меньшие типы с плавающей точкой.

Смотрите примеры мер ниже.

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

Пример - преобразовывающий от double до float

float convert(void) {

    double diam = 1e100;
    return (float)diam;
}

В операторе возврата переменная diam, типа double (64 бита), преобразована в переменную плавания типа (32 бита). Однако значение 1^100 требует, чтобы больше чем 32 бита были точно представлены.

Описание

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

Точное выделение ресурсов хранения для различных типов с плавающей точкой зависит от вашего процессора. Смотрите Target processor type (-target).

Риск

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

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Используйте этот список событий, чтобы определить, как переменные в переполняющемся вычислении получают свои текущие значения. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.

Смотрите примеры мер ниже.

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

Пример - умножение плаваний

#include <float.h>

float square(void) {

   float val = FLT_MAX;
   return val * val;  
}

В операторе возврата переменная val умножается отдельно. Квадрат максимального значения плавающего не может быть представлен плаванием (тип возврата для этой функции), потому что значение val является максимальным значением плавающим.

Исправление — различный тип хранения

Одно возможное исправление должно сохранить результат операции в большем типе данных. В этом примере, путем возврата double вместо float, фиксируется дефект переполнения.

#include <float.h>

double square(void) {
    float val = FLT_MAX;

    return (double)val * (double)val;  
}

Описание

Float division by zero происходит, когда знаменатель операции деления может быть числом с плавающей точкой с нулевым знаком.

Риск

Деление на нуль может привести к катастрофическому отказу программы.

Фиксация

Фиксация зависит от первопричины дефекта. Часто детали результата показывают последовательность событий, которые привели к дефекту. Используйте этот список событий, чтобы определить, как переменная знаменателя получает нулевое значение. Можно реализовать закрепление на любом событии в последовательности. Если детали результата не показывают историю события, можно проследить использование, щелкните правой кнопкой по опциям по исходному коду и смотрите предыдущие связанные события. См. также Интерпретируют Результаты Polyspace Bug Finder.

Это - хорошая практика, чтобы проверять на нулевые значения знаменателя перед делением и обработать ошибку. Вместо того, чтобы выполнить деление непосредственно:

res = num/den;
используйте библиотечную функцию, которая обрабатывает нулевые значения знаменателя прежде, чем выполнить деление:
res = div(num, den);

Смотрите примеры мер ниже.

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

Пример - деление числа с плавающей точкой нулем

float fraction(float num)
{
    float denom = 0.0;
    float result = 0.0;

    result = num/denom;

    return result;
}

Ошибка деления на нуль происходит в num / denom, потому что denom является нулем.

Исправление — проверка перед делением

float fraction(float num)
{
    float denom = 0.0;
    float result = 0.0;

    if( ((int)denom) != 0)
        result = num/denom;

    return result;
}

Перед делением добавьте тест, чтобы видеть, является ли знаменатель нулем, проверяя, прежде чем деление произойдет. Если denom всегда является нулем, это исправление может произвести дефект мертвого кода в ваших результатах Polyspace®.

Исправление — знаменатель изменения

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

float fraction(float num)
{
    float denom = 2.0;
    float result = 0.0;

    result = num/denom;

    return result;
}

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

Группа: Rec. 05. Плавающая точка (FLP)

Введенный в 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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