CERT C: Rec. FLP03-C

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

Описание

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

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

Реализация Polyspace

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

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

  • Переполнение с плавающей точкой.

  • Деление на нули.

Примеры

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

Проблема

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

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

Риск

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

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

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

Исправить дефект можно путем:

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

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

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

См. примеры исправлений ниже.

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

Пример - Преобразование из double на float
float convert(void) {

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

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

Проблема

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

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

Риск

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

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

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

См. примеры исправлений ниже.

Если вы не хотите устранять проблему, например, когда вы обрабатываете бесконечности в коде, добавляйте комментарии к своему результату или коду, чтобы избежать другого рассмотрения. Смотрите Адрес Результаты 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 происходит, когда знаменателем операции деления может быть нулевое число с плавающей точкой.

Риск

Деление на нули может привести к сбою программы.

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

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

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

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;
}

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

Группа: Рек. 05. Плавающая точка (FLP)
Введенный в R2019a

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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