ページ ツリー

 コンテンツ

QAC 9.1.0 / QAC++ 4.1.0 (PRQA Framework 2.1.0) 以降

 QAC / QAC++ のデータフロー解析(DFA)は、関数ごとに実施されますが、『関数間解析』の設定によって関数を跨るデータの追跡を行うことができます。

関数間解析の設定だけの場合、データの追跡は同一の翻訳単位内の関数に限られますが、関数間解析の設定に加えて翻訳単位間データフロー解析(ITU)の設定をすることで、異なる翻訳単位の関数についてデータの追跡を行うことができます。

ITU は  -prodoption オプションで設定します。

 -prodoption df::cma- : ITU を実施しない(デフォルト)
 -prodoption df::cma+ : ITU を実施する

※ QAC 8.2.2 / QAC++ 3.2.2 (PRQA Framework 1.0.5) 以前は ITU を実施することはできません

次の例では、test2.c の翻訳単位に定義された関数 func2 から test1.c の翻訳単位に定義された関数 func1 が呼び出されています。このデータの追跡を行うには、すわなち test2.c の4行目で変数 a が取り得る値を判断するにはITUが必要です。

/*** test1.c ***/
int func1(void){ 
  return 0; 
}
/*** test2.c ***/
int func2(int n){ 
  int a; 
  int r; 
  a = func1(); 
  r = n / a; 
  return r; 
}


解析を2回実施する   ※QAC 10.4.0 / QAC++ 5.4.0 (Helix QAC 2022.3) 以前

ITU を含めてデータフロー解析は qac / qacpp  コンポーネントによる『1次解析』で実施されます。1次解析は翻訳単位ごとに実施されます。
ITU を実施する場合、解析される翻訳単位の順序によって解析結果に影響が出る可能性があります。

上の test1.c, test2.c の例で説明します。

・func1 の翻訳単位が先に解析された場合

func2 の解析時に func1 の結果を利用して変数 a の取り得る値を特定することができます。
そのため func2 の 5 行目にはメッセージ2831が出力されます。

メッセージ2831 D: 明らかにゼロで除算しています。


・func2 の翻訳単位が先に解析された場合

func2 の解析時に func1 の結果が存在しないため変数 a の取り得る値を特定することができません。
そのため func2 の 5 行目にはメッセージ2834が出力されます。

メッセージ2834 P: ゼロ除算が発生する可能性があります。


解析順序による結果の違いを防ぐために、ITU を実施する場合は解析を2回実施することをお勧めします。
2回解析を実施すると、少なくとも2回目の解析時に1回目の解析結果を使用することができます。
つまり上述の例で、必ず func1 の結果が存在する状態で func2 の解析を行うことができるようになり、より精度の高い解析になります。

2回の解析を行う方法は『ITUの設定』をご覧ください。