• Imagix 4D ユーザガイド
  • 目次

[関数相互参照] レポート

一連の [関数相互参照] レポートは、コード内の関数呼び出し階層における特有の側面を解析し、プロジェクト全体に対する結果をまとめます。関数間のデータフローを追跡する [関数フローチェック] とは異なり、[関数相互参照] レポートは、関数間および関数ポインタを介し直接実行された呼び出しのみを調査対象とします。

[ポインタによる呼出し] レポート

ベクタテーブルの作成やコールバック関数のサポートを目的に関数ポインタを使用することは、それらを有用にする一方で、設計もしくはコーディングで発生するミスが、のちに悪影響を及ぼす副作用を生み出すことがあります。あらゆる関数ポインタの使用および、このポインタを介して実行される可能性がある呼び出しをリスト化することで、[ポインタによる呼出し] レポートは、ソフトウェアの本体で使用される関数ポインタを体系的に確認する、有用な参照情報を提供します。次のスクリプトを例として取りあげます。

#include <stdio.h>

typedef void (*FCPTR)() ;

void f0() {	printf("In f0! \n") ; }
void f1() {	printf("In f1! \n") ; }
void f2() {	printf("In f2! \n") ; }
void f3() {	printf("In f3! \n") ; }
void f4() {	printf("In f4! \n") ; }

//---------------------------------------------------		
FCPTR getFuncPtr(int i, FCPTR*  fptrs) {

	if (i >=0 && i <= 1 ) 	return fptrs[i] ;
	else 					return &f4 ; 
}
//---------------------------------------------------
void assignFuncPtr(FCPTR * fp) {	*fp = &f3; }
//---------------------------------------------------
struct OUTER_STRUCT {
     struct {
		int 	m_i;
		FCPTR 	m_inner_fp;
     } 		INNER_STRUCT[3];
	 
	FCPTR 	m_fp;
    float 	m_x;
    } 		
		s1 = { {{ 0, f2 }}, 		f1, 5.0  } ; 
		
FCPTR g_fptrs[5] ; 

//---------------------------------------------------
void useIndirectRef(FCPTR * ptr2fptr) {
	(*ptr2fptr)(); 
}
//---------------------------------------------------
void useStruct(struct OUTER_STRUCT * s2) {
	(s1.m_fp)();  						// f1
	(s2->INNER_STRUCT[2].m_inner_fp)(); // f2
}
//---------------------------------------------------
int useLocArr() {

	FCPTR fptrs[3] ; 
	fptrs[0] = &f0;
	fptrs[1] = &f1;
	fptrs[2] = &f2;

	int n; 
	printf("which function? Enter 0,1,2...\n"); 
	scanf("%d", &n); 
	
	switch (n) {
	case 0: 
	case 1: 	fptrs[n](); break;
	default: 	fptrs[0]();  
	}	// コンパイラによる検出: fptrs[2] の呼び出しが実行されることはありません
}
//---------------------------------------------------
void useAsRetVal() {	
		getFuncPtr(-1, g_fptrs)(); 		// f4
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++
int main(int argc, char* argv[])	{
	
	FCPTR 	fptr			= f0; 
	FCPTR * ptr2fptr 		= &fptr; 
	struct OUTER_STRUCT s2 	= 
		{ { {0, f0}, {1, f1} , {2, f2} },  f0, 5.0  } ; 
	
	fptr(); 							// f0
	assignFuncPtr(&fptr); 			
	(*fptr)(); 							// f3

	useIndirectRef(ptr2fptr); 			// 間接的: f3
	useStruct(&s2); 					// 間接的: f1 および f2
	useLocArr(); 						// 間接的: f0 または f1
	useAsRetVal();						// 間接的: f3
}

出力されたレポートには、関数ポインタを介して呼び出しを実行する関数がすべて表示されます。可能な場合には、呼び出し用の潜在的なターゲット関数のリストも併せて示されます。関数ポインタの解決における制約のため、潜在的なターゲットのリストには呼び出されない関数が含まれることや、逆に呼び出された関数が含まれないことがあります。Imagix 4D の関数ポインタの解決に関する詳細は、ユーザガイドの [C/C++コードの解析] のページに記載されています。

Calls Via Function Pointers

Function                                  File (Line)
          Line of Call
              Function Pointer
                  Potential Target Functions

main                                      fp1.c (66)
          73:     fptr(); 							// f0
              fptr                                      fp1.c (68)
                  f0  f3  
          75:     (*fptr)(); 							// f3
              fptr                                      fp1.c (68)
                  f0  f3  
useAsRetVal                               fp1.c (62)
          63:     getFuncPtr(-1, g_fptrs)(); 		// f4
              return                                    fp1.c
                  f4  
useIndirectRef                            fp1.c (35)
          36:     (*ptr2fptr)();
              ptr2fptr                                  fp1.c (35)
                  f0  f3  
useLocArr                                 fp1.c (44)
          57:     case 1: 	fptrs[n](); break;
              fptrs[]                                   fp1.c (46)
                  f0  f1  f2  
          58:     default: 	fptrs[0]();
              fptrs[]                                   fp1.c (46)
                  f0  f1  f2  
useStruct                                 fp1.c (39)
          40:     (s1.m_fp)();  						// f1
              m_fp                                      fp1.c (27)
                  f0  f1  
          41:     (s2->INNER_STRUCT[2].m_inner_fp)(); // f2
              m_inner_fp                                fp1.c (24)
                  f0  f1  f2  

[再帰関数] レポート

[再帰関数] レポートでは、直接的あるいは他の関数への呼び出しを介して間接的な形で、再帰的に自分自身を呼び出す関数をすべて検出します。再帰関数を使用することで実装が簡単になりますが、無限ループが発生しないように注意し、再帰終了条件が適切であることを確認する必要があります。組込みソフトウェアについては、スタックのオーバーランの危険性があるため、再帰関数は特に注意して使用することが重要です。レポート結果をレビューし再帰処理の最大数を試算したりテストしたりすることで、十分なスタックスペースを確保することができます。次にソースコードの例を示します。

void funcD() {
    return;
}

void funcC() {
    funcA();
    funcD();
}

void funcB(int paramX) {
    while (paramX < 10) paramX = funcB(paramX);
    funcC();
}

void funcA() {
    funcB(1);
    funcC();
}

このソースコードの再帰処理を表示すると [再帰関数] レポートは、直接的あるいは間接的に再帰可能なあらゆる関数と、この再帰処理が発生するパスをリスト化します。また、このリストには表形式が適用されます。各再帰パスのリストでは、再帰処理に関係する関数のみが表示されます。再帰関数それぞれに対して、複数の再帰パスが存在することがあります。

Recursive Functions

Function                               File
          Recursive Path

funcA                                  recursive_funcs.c
      0   . funcA                                                             
      1   . . funcB                                                           
      2   . . . funcB                                      see (1)
      3   . . . funcC                                                         
      4   . . . . funcA                                    recursion
      5   . . funcC                                        see (3)

funcB                                  recursive_funcs.c
      0   . funcB                                                             
      1   . . funcB                                        recursion
      2   . . funcC                                                           
      3   . . . funcA                                                         
      4   . . . . funcB                                    recursion
      5   . . . . funcC                                    see (2)

funcC                                  recursive_funcs.c
      0   . funcC                                                             
      1   . . funcA                                                           
      2   . . . funcC                                      recursion
      3   . . . funcB                                                         
      4   . . . . funcC                                    recursion
      5   . . . . funcB                                    see (3)

[未使用コード] レポート

[未使用コード] レポートには、プロジェクト内のすべてのルート関数がリストされています。これらはコード内の他の関数から呼び出されない関数で、定義したタスクのエントリ関数でもなく、デッドコード領域へのエントリポイントの候補となる関数です。補完的なレポートとして、到達不能な文があります。これは、関数内部のプログラムロジックのために到達不能な特定の文を識別します。

リスト内のルート関数の一部は、実行可能ファイル自体へのエントリポイントである可能性があります。その他の関数は、静的に不定な関数ポインタを介して呼び出されるかもしれません(詳細は解析の問題を参照してください)。そのため、ある程度の手動でのレビューが必要ですが、レポートは可能なデッドコードエントリポイントの完全なリストを示します。

[未使用コード] レポートは、各ルート関数から到達可能な未使用コードの範囲を示します。合計関数数と合計行数の値には、ルート関数自体と、それが一意に呼び出す関数の両方が含まれます。これらは、単一のルート関数からのみ呼び出され、他の関数からは呼び出されない追加の関数です。この範囲はレポート内のリンクを介してグラフィカルにも表示されます。

[変数の使用] レポート

Imagix 4D は搭載されているさまざまなツールを活用することにより、ソフトウェアに存在する個々の関数や変数の相互作用に対して詳細な解析を行う、豊富な機能を提供します。その一方で [変数の使用] レポートでは、あらゆる変数の使用に関する概要を出力します。このレポートは、コードのあらゆる非ライブラリ関数をともなう、グローバル変数、静的変数、メンバ変数をリスト化し、関数が変数を設定したり読み取ったりする各インスタンスを示します。

以下のレポートは、前述の「ポインタによる呼出し」のセクションに記載のソースコード例を使用して生成されたものです。オプションを使用することで、横軸と縦軸を入れ替えることができます。

Functions Use of Variables

Key:
        R:                variable is read only
        S:                variable is set only
        U:                variable is used, both read and set

Settings:
        Global Variables:  displayed
        Static Variables:  displayed
        Member Variables:  displayed

                                         Variables  g_fptrs
                                                    . INNER_STRUCT
                                                    . . m_fp
                                                    . . . m_i
                                                    . . . . m_inner_fp
                                                    . . . . . m_x
                                                    . . . . . . return
                                                    . . . . . . . s1
Functions
assignFuncPtr ....................................  . . . . . . . . 
f0 ...............................................  . . . . . . . . 
f1 ...............................................  . . . . . . . . 
f2 ...............................................  . . . . . . . . 
f3 ...............................................  . . . . . . . . 
f4 ...............................................  . . . . . . . . 
getFuncPtr .......................................  . . . . . . . . 
main .............................................  . . . . . . . . 
useAsRetVal ......................................  R . . . . . . . 
useIndirectRef ...................................  . . . . . . . . 
useLocArr ........................................  . . . . . . . . 
useStruct ........................................  . R R . R . . R