未定義の識別子に関する Polyspace コンパイル エラーの修正
問題
Polyspace® の検証がコンパイル段階で失敗し、未定義の識別子に関するメッセージが表示されます。
このメッセージは、Polyspace で変数定義が見つからないことを示しています。したがって、変数タイプが特定できません。
考えられる原因: ファイルが見つからない
対象のソース コードに変数定義が含まれていません。たとえば、Polyspace で見つからないインクルード ファイルで変数が定義されている場合などです。
ソース コードで #include されたインクルード ファイルが Polyspace プロジェクトに追加されていない場合、事前の警告が表示されます。
Warning: could not find include file "my_include.h"
解決法
変数定義がインクルード ファイルにある場合は、そのインクルード ファイルを含むフォルダーを追加します。
Polyspace デスクトップ製品のユーザー インターフェイスで、このフォルダーをプロジェクトに追加します。
詳細については、ユーザー インターフェイスでの Polyspace の実行を参照してください。
コマンド ラインで、コマンド
polyspace-bug-finderにフラグ-Iを使用します。詳細は、
-Iを参照してください。
考えられる原因: 認識されないキーワード
変数ではコンパイラで認識されるキーワードが表現されていますが、ANSI® C 標準の一部ではありません。したがって、Polyspace では認識されません。
たとえば、一部のコンパイラは __SP をスタック ポインターへの参照として解釈します。
解決法
Polyspace で認識されないキーワードを変数が表現している場合は、ソース コードまたは前処理済みのコードに由来するキーワードを置き換えるか削除します。
前処理済みのコードに由来するキーワードを削除するか置き換えると、ソース コードはそのままでコンパイル エラーを回避できます。次のいずれかを行います。
解析オプションを使用して、未知の各キーワードを置き換えるか削除します。コンパイラ固有のキーワードを ANSI C 規格の対応するキーワードに置き換えます。
解析オプションについての詳細は、
[プリプロセッサ定義] (-D)を参照してください。#define命令を使用して、未知のキーワードを別のヘッダー ファイルで宣言します。そのヘッダー ファイルを、解析オプションを使用して指定します。解析オプションについての詳細は、
インクルード (-include)を参照してください。ヘッダー ファイルの例は、コンパイル オプションの効率的な収集を参照してください。
考えられる原因: 宣言が #ifdef ステートメントに組み込まれている
変数がプリプロセッサ命令 #ifdef の分岐で宣言されています。たとえば、変数 macro_namemax_power の宣言が次のようになっているとします。
#ifdef _WIN32 #define max_power 31 #endif
コンパイル ツールチェーンでは、マクロ macro_name が暗黙的に定義されていると見なされ、#ifdef の分岐が実行される可能性があります。しかし、Polyspace のコンパイルでは、マクロが定義されていると見なされない場合があります。そのため、#ifdef の分岐が実行されず、変数 max_power が宣言されません。
解決法
コンパイル エラーを回避するには、以下のいずれかを行います。
[ターゲットおよびコンパイラ] のオプションを使用して、コンパイラを直接指定します。たとえば、Visual C++® コンパイラをエミュレートするには、[コンパイラ] を
[visual12.0]に設定します。ターゲットおよびコンパイラを参照してください。オプション
[プリプロセッサ定義] (-D)を使用してマクロを明示的に定義します。
メモ
ビルド コマンドをトレースして Polyspace を作成した場合は、[ターゲットおよびコンパイラ] のほとんどのオプションが自動的に設定されます。
考えられる原因: プロジェクトがデバッグ ビルド以外から作成されている
これが原因になる可能性があるのは、assert ステートメント (または ASSERT や VERIFY など等価の Visual C++ マクロ) に未定義の識別子がある場合だけです。
通常、このエラーには以下のようにして遭遇します。Polyspace プロジェクトがデバッグ モード以外でビルド システムから作成されています。このプロジェクトの解析を実行すると、assert ステートメントに未定義の識別子があるためにコンパイル エラーが発生します。たとえば、識別子 my_identifier が #ifndef NDEBUG で次のように定義されているとします。
#ifndef NDEBUG int my_identifier; #endif
C 標準では、NDEBUG マクロが定義されている場合、すべての assert ステートメントを無効にしなければなりません。
ほとんどの IDE では、NDEBUG マクロはビルド システムで定義されます。IDE でソース コードをビルドする場合、デバッグ モード以外では前処理で #ifndef NDEBUG ステートメントのコードが削除されます。たとえば、前述の例では、my_identifier が定義されません。my_identifier が assert ステートメントにしかない場合、assert ステートメントは NDEBUG で無効にされるため、いずれも使用されません。未定義の識別子によるコンパイル エラーは発生せず、ビルド システムが正常に実行されます。
Polyspace では、検証を強化するために内部で assert ステートメントが使用されているため、NDEBUG マクロが定義されていても assert ステートメントは無効にされません。
ビルド システムから Polyspace プロジェクトを作成する場合、ビルド システムで NDEBUG マクロが定義されていると、Polyspace プロジェクトに対しても定義されます。Polyspace では、前処理で #ifndef NDEBUG ステートメントのコードは削除されますが、assert ステートメントは無効になりません。コードの assert ステートメントが #ifndef NDEBUG ステートメントのコードに依存していると、コンパイル エラーが発生する可能性があります。
前述の例の場合は、次のようになります。
my_identifierの定義が前処理で削除されます。assertステートメントは無効になりません。識別子my_identifierがassertステートメントで使用されると、my_identifierが定義されていないためエラーが発生します。
解決法
この問題を回避するには、Polyspace プロジェクトをビルド システムからデバッグ モードで作成します。ビルド システムをデバッグ モードで実行する場合、NDEBUG は定義されません。このビルドから Polyspace プロジェクトを作成すると、Polyspace プロジェクトに対して NDEBUG が定義されません。
プロジェクトの設定に応じて、デバッグ モードでのビルドを有効にするオプションを使用します。たとえば、ビルド システムが gcc ベースの場合は、DEBUG マクロを定義し、NDEBUG の定義を解除できます。
gcc -DDEBUG=1 -UNDEBUG *.c
あるいは、オプション [プリプロセッサ定義] (-D) を使用して前処理済みのコードの assert ステートメントを無効にできます。ただし、Polyspace では assert ステートメントをエミュレートできなくなります。