メインコンテンツ

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

CERT C: Rec.FLP03-C

Detect and handle floating-point errors

説明

ルール定義

浮動小数点のエラーを検出および処理します。1

Polyspace 実装

ルール チェッカーは以下の問題をチェックします。

  • 浮動小数点変換のオーバーフロー

  • 浮動小数点のオーバーフロー

  • 浮動小数点数のゼロ除算

チェッカーの拡張

入力値が不明であり、入力のサブセットのみがエラーの原因として考えられる場合、既定の Bug Finder 解析ではこのルールに対する違反が報告されない場合があります。特定のシステム入力値を原因とする違反の有無をチェックするには、より厳密な Bug Finder 解析を実行してください。特定のシステム入力値から欠陥を見つけるための Bug Finder チェッカーの拡張を参照してください。

すべて展開する

問題

浮動小数点変換のオーバーフローは、浮動小数点数をより小さい浮動小数点データ型に変換するときに発生します。変数に、元の数を表現するだけの十分なメモリがない場合、変換はオーバーフローします。

異なる浮動小数点型への正確なストレージ割り当てはプロセッサに依存します。ターゲット プロセッサ タイプ (-target)を参照してください。

リスク

オーバーフローにより、計算の結果が予期しない値になる場合があります。実装に使用している丸めモードに応じて、結果が無限大または最大の有限値になる可能性があります。以降の計算でオーバーフローの発生した変換の結果を使用しており、オーバーフローを考慮していない場合、予期しない結果になることがあります。

修正方法

修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。このイベント リストを使用して、変換対象の変数がどのように現在の値を取得したのかを確認します。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

この欠陥は次のようにして修正できます。

  • すべての値に適応できるように、変換の結果に対してより大きいデータ型を使用。

  • オーバーフローにつながる値をチェックし、適切なエラー処理を実行。

一般的に、より小さい浮動小数点型への変換は避けます。

以下の修正例を参照してください。

問題を修正しない場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

既定では、Bug Finder 解析は無限大と NaNs を認識しません。結果が無限大および NaNs になる演算には、欠陥としてフラグが設定される可能性があります。コードで無限大および NaN の値を処理するには、オプション [非有限の浮動小数点を検討] (-allow-non-finite-floats) を使用します。

例 - double から float への変換
float convert(void) {

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

return ステートメントで、double 型 (64 ビット) の変数 diam が float 型 (32 ビット) の変数に変換されています。しかし値 1^100 を正確に表現するには、33 ビット以上が必要です。

問題

浮動小数点のオーバーフローは、浮動小数点変数に対する演算が、結果のデータ型では表せない値になる可能性がある場合に発生します。変数のデータ型によって、変数ストレージに割り当てられるバイト数が決まり、許容される値の範囲が制限されます。

異なる浮動小数点型への正確なストレージ割り当てはプロセッサに依存します。ターゲット プロセッサ タイプ (-target)を参照してください。

リスク

オーバーフローにより、計算の結果が予期しない値になる場合があります。実装に使用している丸めモードに応じて、結果が無限大または最大の有限値になる可能性があります。以降の計算でオーバーフローの発生した計算の結果を使用しており、オーバーフローを考慮していない場合、予期しない結果になることがあります。

修正方法

修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。このイベント リストを使用して、オーバーフローの発生した計算で変数がどのように現在の値を取得したのかを確認します。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

以下の修正例を参照してください。

問題を修正しない場合、たとえば、コード内で無限大を処理する場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

既定では、Bug Finder 解析は無限大と NaNs を認識しません。結果が無限大および NaNs になる演算には、欠陥としてフラグが設定される可能性があります。コードで無限大および NaN の値を処理するには、オプション [非有限の浮動小数点を検討] (-allow-non-finite-floats) を使用します。

例 - 浮動小数点の乗算
#include <float.h>

float square(void) {

   float val = FLT_MAX;
   return val * val;   //Noncompliant
}

return ステートメントで、変数 val にそれ自身を乗算しています。val の値は浮動小数点の最大値であり、浮動小数点の最大値の 2 乗は浮動小数点 (この関数の戻り値の型) では表現できません。

修正 — 異なるストレージ型

1 つの修正方法として、演算の結果をより大きいデータ型に保存することができます。この例では、float ではなく double を返すことでオーバーフローの欠陥を修正できます。

#include <float.h>

double square(void) {
    float val = FLT_MAX;

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

浮動小数点数のゼロ除算は、除算演算の分母 (除数) がゼロ値の浮動小数点数になる可能性がある場合に発生します。

リスク

ゼロ除算はプログラムをクラッシュさせる可能性があります。

修正方法

修正方法は欠陥の根本原因によって異なります。多くの場合、結果の詳細には欠陥につながる一連のイベントが表示されます。このイベント リストを使用して、分母変数がどのようにゼロ値を取得したのかを確認します。そのシーケンス内のどのイベントについても修正を実装できます。結果の詳細にイベント履歴が表示されない場合は、ソース コード内で右クリック オプションを使用して逆のトレースを行い、これまでの関連するイベントを確認できます。Polyspace デスクトップ ユーザー インターフェイスでの Bug Finder の結果の解釈も参照してください。

除算の前に分母がゼロ値かどうかをチェックしてエラーを処理することをお勧めします。次のように除算を直接実行するのは避けます。

res = num/den;
除算を実行する前に分母のゼロ値を処理するライブラリ関数を使用します。
res = div(num, den);

以下の修正例を参照してください。

問題を修正しない場合、たとえば、コード内で無限大を処理する場合は、改めてレビューされないように結果またはコードにコメントを追加します。詳細は、以下を参照してください。

既定では、Bug Finder 解析は無限大と NaNs を認識しません。結果が無限大および NaNs になる演算には、欠陥としてフラグが設定される可能性があります。コードで無限大および NaN の値を処理するには、オプション [非有限の浮動小数点を検討] (-allow-non-finite-floats) を使用します。

例 - 浮動小数点数のゼロでの除算
float fraction(float num)
{
    float denom = 0.0;
    float result = 0.0;

    result = num/denom; //Noncompliant

    return result;
}

denom がゼロであるため、num/denom でゼロ除算エラーが発生します。

修正 — 除算の前にチェック
float fraction(float num)
{
    float denom = 0.0;
    float result = 0.0;

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

    return result;
}

除算の前に、分母がゼロかどうかを確認するためのテストを追加して、除算が実行される前にチェックします。denom が常にゼロである場合は、この修正により Polyspace® の結果にデッド コードの欠陥が報告される可能性があります。

修正 — 分母を変更

1 つの修正方法として、denom がゼロでなくなるように分母の値を変更することができます。

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

    result = num/denom;

    return result;
}

チェック情報

グループ: Rec.05.浮動小数点 (FLP)

バージョン履歴

R2019a で導入


1 This software has been created by MathWorks incorporating portions of: the “SEI CERT-C Website,” © 2017 Carnegie Mellon University, the SEI CERT-C++ Web site © 2017 Carnegie Mellon University, ”SEI CERT C Coding Standard – Rules for Developing safe, Reliable and Secure systems – 2016 Edition,” © 2016 Carnegie Mellon University, and “SEI CERT C++ Coding Standard – Rules for Developing safe, Reliable and Secure systems in C++ – 2016 Edition” © 2016 Carnegie Mellon University, with special permission from its Software Engineering Institute.

ANY MATERIAL OF CARNEGIE MELLON UNIVERSITY AND/OR ITS SOFTWARE ENGINEERING INSTITUTE CONTAINED HEREIN IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.

This software and associated documentation has not been reviewed nor is it endorsed by Carnegie Mellon University or its Software Engineering Institute.