Undestand の解析
Understand の C 言語で抽出できない依存関係について、サンプルコードを用いて説明します。
確認バージョン
• Understand 3.0 (Build 640)
• Understand 3.1 (Build 700)
• Understand 4.0 (Build 788)

抽出できない依存関係
Understand の C 言語の解析（Fuzzy/Strict）で、抽出できない依存関係には、以下があります。
• ポインタ関連• 関数ポインタによる関数の呼び出し• 関数テーブル（ジャンプテーブル）• ポインタ変数のアドレス操作
上記例以外でも、ポインタ経由の操作については依存関係を解析できません（例:コールバック関数）• 同名定義関数ポインタによる関数の呼び出し
サンプルコード
01
02
03
04
05
06
07
08
09
10
1112131415#include <stdio.h>void (*pf)(char*);void func(char* c) {printf("%s¥n", c);}void foo1() {pf = func;}
void foo2() {pf("hello");}
1/9

1617181920212223242526

void foo3() {func("world");}
int main() {foo1();foo2();
foo3();
return 0;}[Fuzzy/Strict 解析]
main 関数の Calls Graph
Calls Graph のコンテキストメニュー[Function Pointer]を[On]に切り替えた場合、情報ブラウザーのReferences で表示される「call-deref」の関数ポインタのアドレス参照や「pointer」で表示される関数への呼び出しが表示されます。しかし、関数ポインタ(pf)に関数アドレスを代入する処理(10 行目)も、関数呼び出しと見なされ、表示されます。
• コンテキストメニュー[Function Pointer]-[Off]の場合：
実際の関数呼び出しのみ表示します。

• コンテキストメニュー[Function Pointer]-[On]の場合：
情報ブラウザーの Calls セクション内の• 「void func(char *) sample.c(10) pointer」で示されている、関数へのポインタ宣言• 「pf sample.c(14) call-deref」で示されている、デリファレンス（参照外し）による関数呼び出しが表示されますが、デリファレンスで呼び出される関数の実体（この場合 func）を解析することができません。

2/9

main 関数の情報ブラウザーの表示

関数ポインタ(pf)の情報ブラウザーの表示
pf の実体が func()であることが解析できません。

3/9

関数テーブル（ジャンプテーブル）
サンプルコード
0102
03
0405
06
0708
09
10
1112131415161718192021#include <stdio.h>void Event01(){ printf("Event01¥n"); };void Event02(){ printf("Event02¥n"); };void Event03(){ printf("Event03¥n"); };void (*funcTable[])() ={Event01,Event02,Event03};
int foo(){
int i;for ( i = 0; i < 3; i++ ){funcTable[i](1);}return 0;}[Strict 解析]
funcTable のデリファレンスによる関数呼び出しとして解析されますが、関数の実体(Event01, Event02,Event03)を解析できません。
foo 関数の Calls Graph

4/9

funcTable の情報ブラウザーの表示[Fuzzy 解析]
デリファレンスによる関数呼び出しとしても表示されません。funcTable 配列オブジェクトの Use として処理されます。

ポインタ変数のアドレス操作
サンプルコード
0102
03
04
05
06
07
08
09
10
11
12
13
14
15
16
1718
1920
21
22
23
24

#include <stdio.h>
typedef struct {int x;
int y;int z;} STRC;int main(){STRC data;
STRC *dataPtr;
data.x = 1;
data.y = 2;
data.z = 3;
dataPtr = &data;
dataPtr->x = data.z;
printf("%d, %d", dataPtr->x, dataPtr->y);}return 0;[Fuzzy/Strict 解析]
ポインタ変数にアドレスを渡して、そのポインタ先でアドレス操作した場合、その実体との参照関係は表示できません。
上記の例では、ポインタ変数(dataPtr)から、実体(data)のメンバーへのアクセスは(20 行目を data.x への Set,21 行目を data.y への Use として)検出できません。

5/9

構造体の実体(data)の情報ブラウザーの表示

同名・多重定義
C 言語の場合、実際のコンパイル単位では、同名の変数・関数は多重定義することはできません。Understandでは、同名・多重定義があった場合もエラーを発生しないで解析可能ですが、同名の変数や関数への参照は、正しい解析結果が得られない場合があります。
対応方法
プロジェクトから同名定義を取り除いたプロジェクト単位で解析するようにしてください。
サンプルコードのディレクトリ構造

サンプルコード(a/bar.h)01020304050607080910111213#ifndef BAR_H#define BAR_H
struct AAA {int a;
int b;};
struct AAA aaa;
int gnum = 100;void func(int);#endif BAR_H

6/9サンプルコード(a/foo.c)
0102030405
0607080910#include <stdio.h>#include "bar.h"void func(int num){
aaa.a = 1;
aaa.b = 2;
gnum = 100;printf("a:%d", num);}

サンプルコード(b/bar.h)010203
0405
06
0708

struct AAA {int a;
int b;};
struct AAA aaa;
int gnum = 200;
void func(int);

サンプルコード(b/foo.c)
0102
03
04
05
06
0708
09
10

#include <stdio.h>#include "bar.h"void func(int num){
aaa.a = 10;
aaa.b = 20;
gnum = 200;
printf("b:%d", num);}

サンプルコード(main.c)
01
02
03
04
05
06
0708
09
10
11
12
13
14
15
16

#include <stdio.h>#include "bar.h"
int main(){
int num = 10;
func(num);
gnum = 300;func(gnum);
aaa.a = 10;
aaa.b = 20;}

return 0;

7/9

[Fuzzy 解析]
main 関数の情報ブラウザーの表示

同名の関数(func)が存在することで、定義元が解決できず、未解決のエンティティ（グレーアウト）として処理されています。
[Strict 解析]
main 関数の情報ブラウザーの表示

同名の関数(func)は、a/foo.c で定義されたものとして処理されていますが、複数の同名の要素がある場合、その定義元はランダムで参照されます。そのため、下記のように、b/foo.c の func 関数への呼び出しとして解析される場合もあります。
8/9

Understand のオーバーライドの設定機能で、ファイルやディレクトリに対して、例えばインクルードディレクトリを個別に設定することができます。しかし、この設定をおこなっても、エンティティの種類によっては解析結果に反映されない場合があります。
[Fuzzy/Strict 解析]
グローバル変数(b/bar.h の gnum)の情報ブラウザーの表示

b/bar.h で宣言されているグローバル変数 gnum が、a/foo.c と b/foo.c の func 関数の両方から参照関係があると解析されています。

9/9