exponenta event banner

Поглощение поплавкового операнда

Один операнд сложения или вычитания поглощается другим операндом

Описание

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

Риск

Избыточные операции тратят время на выполнение вашего процессора.

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

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

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

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

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

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

Чтобы определить, когда один операнд пренебрежимо мал по сравнению с другим операндом, дефект использует правила, основанные на стандартах IEEE ® 754. Чтобы исправить дефект, вместо использования фактических правил можно использовать эту эвристику: отношение большего к меньшему операнду должно быть меньше, чем2p-1 по крайней мере для некоторых значений. Здесь, p равен 24 для 32-разрядной точности и 53 для 64-разрядной точности. Для определения точности дефект использует спецификацию для Target processor type (-target).

Этот дефект появляется, только если один операнд всегда пренебрежимо меньше другого операнда. Для просмотра экземпляров субнормальных операндов или результатов используйте флажок Субнормальное плавание в Prover™ кода Polyspace ®.

Примеры

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

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-30)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

float input_signal2(void) {
    float temp = get_signal();
    if(temp > 1.)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    float signal2 = input_signal2();
    float super_signal = signal1 + signal2;
    do_operation(super_signal);
}

В этом примере дефект появляется в добавлении, поскольку операнд signal1 находится в диапазоне (0,1e-30) но signal2 больше, чем 1.

Исправление - Удаление избыточной работы

Одной из возможных корректировок является удаление избыточной операции добавления. В следующем исправленном коде операнд signal2 и связанный с ним код также исключается из рассмотрения.

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-30)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    do_operation(signal1);
}
Исправление - проверка диапазона операндов

Другая возможная коррекция - посмотреть, какие диапазоны операндов вы ожидаете. Например, если один из диапазонов операндов не должен быть незначительным, исправьте проблему, вызывающую малый диапазон. В следующем исправленном коде диапазон (0,1e-2) навязывается signal2 таким образом, он не всегда пренебрежимо мал по сравнению с signal1.

#include <stdlib.h>

float get_signal(void);
void do_operation(float);

float input_signal1(void) {
    float temp = get_signal();
    if(temp > 0. && temp < 1e-2)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

float input_signal2(void) {
    float temp = get_signal();
    if(temp > 1.)
        return temp;
    else {
       /* Reject value */    
       exit(EXIT_FAILURE);
    }
}

void main() {
    float signal1 = input_signal1();
    float signal2 = input_signal2();
    float super_signal = signal1 + signal2;
    do_operation(super_signal);
}

Информация о результатах

Группа: Числовые
Язык: C | C++
По умолчанию: Вкл.
Синтаксис командной строки: FLOAT_ABSORPTION
Воздействие: Высокое
CWE ID: 189, 682, 873
Представлен в R2016b