{printf("BRANCH Block");b四ak;} defauIt:
printf("O唯h氾rBlock"); }
実行給果(部分)
{} Blockー>BlocklD 6291457 BASICBlock‑> BlocklD 6291458 BASICBlock‑> BlocklD 6291459ベ D
BASIC Block‑> BlocklD 6291460ベ 9
{} Block司>BI田:klD 6291461 ‑‑(4) FORBlock‑> BlocklD 6291462 ←‑(3) IFBloc主ー>Block lD 6291463 ←‑{j) BASICBlock‑> BlocklD 6291464 {} Block ‑> Block lD 6291465↓ifblock 6291463 (l) if(i<=10)
k=add(i++,k);←basic block 6291459 (2) else ↓for b10ck 6291462 (3)
第3章 プログラムの構造を解析する 47
forU= 1; j<= 10; j++){←compound block 6291461 (4)
↓basic block 6291460 (5) dec(&i);
3 . 2 ブロック構造の解析
48 Sapidによるソフトウェア解析技法
サンプルプログラム
3‑4
ーブロック構造の解析アルゴリズム:
1.各関数宣言オブジェクト(optionaldecl)を順番に選以以下の手続きを繰り返す 2.その関数宣言のトップブロックを求める
3 .
そのブロックと直接関連を持つブロックのI d
を取得4 . 3 .
で求めたブロックの情報を出力#incIude <stdio.h>
#incIude <Sapid/Sapid.h>
一仇
を章
LJっu Ju
︐/
I f
M︐
h }
O川悦d↑
・伺UH叶H'1dU河
H H
p b I
日
b .
•
︐S・bO0
の一 川刈 h u‑
刈別測も川駅釘‑D副創刊い
d m
J円・叩閣由
m m
四灯油尚治
PL MM m
ιu EU Ru au
官X
LY tt tt
川
mv mV
岬r
mv nE JU JU AU AQ
O汀μ汀μ汀H汀H
LU Lu
‑L υ‑ LU l
‑‑ nu nv nu nu u M凶 凶凶
‑凶
uv qu eu qu cu
?t mMint町 , 伽 骨 岬 日 〕 SpdObjld top̲block̲id, bllUd; int i;
SpdObjldArray opCaπay;
S凶Cursor市lk̲csr; SpdDBld dbld; dbld = spdOpenSDBO;
openModel(dbld);
/ / 1.各関数宣言オブジヱクト (optionaldecI)を同薦書に選び以下の手続きを繰り返す opCaπ~r = ~p~GetO均ldArray("optionaldecI",NULL, NULL);
for (i = 0; i < opcarray.size; i++)
if(spdGetAttfValInt(opt̲array川[i],"sort")==OPT ]UNCDEF){ getFuncName(opCarray.id[i]);
/ / 2
その関数宣言のトップブロックを求めるtop̲block̲id = spdGetARelObj(opCarray.id[i],"func̲bodyγany"); μ 3そ の ブ ロ ッ ク と 直f鵬 を 持 つ ブ ロ ッ
p
のIdを 開 lilk四r=spdGetRel0切lrii:t( t o " . J > 1
田k̲id,"blk̲blk", "p‑id"); whITe ((blk~id = spdGetRelObjt砧 csr))!=SAPID̲NON̲ID) {ぶ i i d 宇・都民需品摘。説立田仇凶,
spdFreeCursor(blk一 回r);
:
主 f : 臨す必蹴叫);
関数
getBlockTrace オブジェクトblockの基本情報を求める
void getBlockTrace(SpdObjld block̲id){SpdObjld blk̲id; ghcumf
龍一国
r'getBlockInfo(block̲id); prinげ("%d ,"block̲id); / / ブロックを下イ方向へたどる
blk3sr = spdGetRelObjlnit(blocLid,"blk̲blk","p‑id"); while((blk"::id = spdGetRelObj(blk3Sr))!=SAPID:"'NON̲ID){
pnnぜ("ー>"); getBlockTrace(blk̲id); spdFreeCursor(blk一 回r); }
第3章 プログラムの構造を解析する 49
実行結果
(main
関数のみ)Funcation main
ぺrop‑> BASIC Block 6291467
ぐrop‑> WHILE Block 6291466‑>{} Block 6291465 ‑>BASIC Block 6291464 ‑>IF Block 6291463
‑>FOR Block 6291462 ‑>{} Block 6291461‑>BASIC Block 6291460‑>BASIC Block 6291459 Trop‑> BASIC Block 6291458
↓while block 6291466↓compoundblock 6291465 while (k< 100) {←basic blocK 6291464
↓ifblock 6291463 if(i<=10)
basic block 6291459→k=add(i++,k); else
↓for block 6291462 ↓compound block 6291461 forU= 1; j<= 10; j++){←basic block 6291460
dec(&i); }
printf("i=%d k=%d¥n",i,k);
[実行結果のブロック構造]
W 変 数 の ト レ ー ス と 制 御 構 造
プログラムの検証やデバッグプロセスでは、変数の値が、制御構造中でどの ように変化するかを分析する。条件式や繰り返し文と、制御ブロックとの関係 も分析する。
クラス
e x p r e s s i o n
とb l o c k
のオブジヱクトを用いて変数の値のトレースを 行うプログラムを作成する。ターゲットとする変数を含む文の所属するブロッ クの種類や構造を調べる。変数の値が変化させられる可能性についても検査す る(左辺値、右左辺値など)。解析対象プログラム
3 ‑ 2
intmainO{
int i=O,j, k= 0; while (k< 100){
{int k; if(i<= 10)
k=i++ + k; else {
i
=
i‑10; k=k‑10; }50 Sapidによるソフトウェア解析技法
} K=i;
品i>r(j=1; j<= 1 0; j++){ k=k+j; i = k;
printf("i=%d k=%d¥n",i,k); retum 0;
4 . 1
変数のトレースとブロック情報(1)ターゲット変数をk とし、当該変数が左辺値として出現する式を順番に取得 し、 どの種類のブロックに属するかを調べる。 式が制御ブロックの条件部等に 属していれば、制御ブロックと直接関連をもっ。
サンプルプログラム
3
・5
変数のトレースとブロック情報(1) アルゴリズム:
1 .
idほ
intiferオブジェクトの中で変数のものを選び以下の手続きを繰り返す 2. その変数を左辺値として含む文のオブジェクトIdを取得3 .
ブロックと直接関連を持つ式(文statement)のIdを取得getStatement 4. 当該ブロックの情報を出力#面面瓦de<stdio:h:;:
#include <SapidjSapid.h>
void OlltmModel(SpdDBld); SpdObjId getBlockIrifo(SpdO巴~Id);
SpdO凶IdgetStatement(SpdOlijld); irit spd..lleUine(SpdObjld);
??t Emmnma副州i耐n凶n1咲
ο
((的柑(
仰巾蜘(加i山nn2s凶DB副Id dめbI叫d也; SpdObjldArray id̲array; SjxlObjld ei'lJr̲id
,
siatemenUd;SpdCursor *ident.田町
mt I,J; dbld = spdOpenSDBO;
openMooel(dbld);
id̲array = spdGetObjldArray("ident泊er"
,
NULL,
NULL);j j 1. ideintiferオブジエクトの中で変数のものを選び以下の手続きを繰り返す for (i =匂i< id̲array.size; i++ )
if( spdGetAt廿.ValIrit(id̲array.id[i],"sort")==ID̲VARIABLE){
printf("¥nη阻%d‑出objectof identifier¥"%s¥"¥n"j+ l,spdGetName(id̲array.id[i])); / j 2.その変数を左辺値として含む文のオブジヱクトIdを耳切尋
ident田r= spdGetRelObjlnit(id̲aπay.id[i],"idencrefγany");
while((expr̲ld = spdGetRelObj(hlent一 回r))!=SAPID̲NON̲ID) if (spdGetAttrValInt(expcid,"lrtype") ==EXPR̲L̲ VALUE){
//3.当該の文と直俊関連を持つブロックを耐尋 statemenUd = getStatement (expr̲id);
}
第
3
章 プログラムの構造を解析する 51//4. 当 ü~'ブロックの情報を出力
getBlockInfo(spdGetARelObj(statement̲id,"blk̲expr","any")); }
prinぜ("¥n");
spdFreeCu
問 。
r(idenC田r); spdFreeObjldArray(id̲array); spdCloseSDB(dbld); retum (EXIT̲SUCCESS);関数
getStatement 一式の情報を求めるSpdO句IdgetStatement(SpdO切Ide法pUd){
SpdObjld expr̲tmp̲id; SpdCursor *expr四r; SpdRel expi̲rel;
expr̲田r= spdGetRelObjlnit(expr̲i札、xpr̲expr","cーid"); wliile((expr"':tmp̲id = spdGetRelObj(expr̲csr))!=SAPID̲NON̲ID){
i臨侮f((色s凶pd.dωe良嗣函Ob蝋.j(e均xP戸r仁リ̲tm一町p̲id,"b叫l政f<
e
田xp戸
f戸,ヘiヘi,勺ケ九ex勾pr~~叫'el= sp凶dGωetAR制eel(加e回xp戸r
凶 一
ι"bl肱ke耳守pr",九n町l川y""つ')pnn百函("¥¥nex却pr戸 % 治sa剖1#%制d
、 て
sp.d品cCω託ωb凶.jTex泊t(e点xp戸rt加mp̲i凶dの), spd‑‑llecline(expr̲tmp̲id)); spdFreeCursor( expr ̲csr);}return expr‑tmpJd
,
elsegetStatement(expr̲tmp̲id);
実行結果(変数
kの結果のみ)
Tbe l‑th object of identifier "k"expr = k=k+j at # 17 BASIC Block expr = k = i at # 15 BASIC Block The 2‑th object 0イidentifier"k"
四pr=k=k‑10at#7 BASICBlock <ー(A)のbas叩block内の式の左辺値での出現 expr = k=i++ + k at # 10 BASIC Block <ー(B)
while (k< 100){ if(i<= 10)
↓(B) basic block内の式の左辺値での出現 k=i++ + k;
else{
} 1 = 1‑10;
↓(A) basic block内の式の左辺値での出現 k=k‑10;
[変数 kの出現とブロック構造 IThe2‑th object of identifier "k") 1
52 Sapidによるソフトウェア解析技法 4.2 変数のトレースとブロック情報(2)
あ る 文 を 含 む 最 上 位 の ブ ロ ッ ク を 求 め る 。 タ ー ゲ ッ 卜 の 変 数 ( ク ラ ス
1 IBASIC I
コ
K2
日 孟 + 団 コ
k図14.
identifier) が属する式と関連blk̲expr
を持つ最内ブロックを、外側へたどり、
得られるブロック情報を取得する。
3 . 2
の関数getBlockTraceの解析方向を上向 きに変える (p‑id→
c‑id)。
サンプルプログラム
3‑6
変数のトレースとブロック情報(2 ) アルゴリズム:
l 変数を左辺値として含む文のオブジェクトIdを取得
2 .
1.で求めた文と直接関連を持つブロックを取得3. 2.で求めた文のブロック情報を最内から順番に出力get
B l
ockTrace、getB l
ocklnfo 自説副示扇面五〉#include <SapidfSapid.h>
void openModel(SpdDBld); SpdObjld getStatement(SpdO句Id); SpdObjld getBlocklnfo(SpdObjld); SpdOb]Id getBlockTrace(SpdObjld); int spd.....geUine(SpdOlljld); int main(int argc, char *argv[]) {
SpdObjldArray id̲array;
SPdOb]Id expr̲id, sfatemenUd, block̲id; SpdCursor
・
ident田 町int i; SpdDBld dbld; dbld = spdOpenSDBO;
openModel(dbld);
id̲array = spdGetO均ldArray("identifier",NULL, NULL);
for (i = 0; i < id̲array.size; i++)
if(s凶Ge凶町ValInt(id_町r!,y.id[})九。六,:'L=~~!?~V品lAB日){
}
p巾 げt"¥n¥nThe%d‑th object (VAR ¥"%s¥")",i+ 1,spdGetName(id̲array.id[i]));
f f
1.変数を左辺値として含む文のオブジェクトIdを耐専ident田r= sp~GetR:elOl?jI!'lt,Ci(:I~array.id[~lパdent refブany"); while((expr̲id = spdGetRelObj(iden
t . . : 白
r))!=SAPID̲NON̲ID) if (spdGetAttrVallnt(expr̲id,
"lrtype") ==EXPR̲L̲ VALUE){f f
2. 1.で求めた文と直接関連を持つブロックを取得 statementーid= getExpression(expr̲id);if((bl凹k̲id=spdGetARelO同(statemen
t . . :
id,
"blk̲expr"、 ,
id"))!=SAPID̲NON̲ID)f f
3. 2.で求めた文のプロック情報を最内から順番に取得getBlockTrace(block̲id); return (EXIT̲SUCCESS);
}
第3章 プログラムの構造を解析する 53
関数 g e t B l o c k T r a c e オブジェクト b l o c k の 基 本 情 報 を 求 め る
void getBlockT回 目SpdObjldblock̲id){ pdObjld blk~id;
int attr̲ val; SpdCursor 市lk田 町
getBlockInf口(block̲id);printf(" %d ,"block̲id);
L(ZtiA& 椅
1 Z 6 a ‑ i札"blk̲b町 トi凶ばdげ"wh悩ile((仏blk
一
‑=id= spdGetRelO~削~(blk】k c回sr))!=SAPID一
NON̲ID){prinぜ("ー>"); getBlockTrace(blk̲id); spdFr田Cursor(blk一 回r);
実行結果(部分)
甘 児 島thobject of identifier "k"
expr= k~k-10at 町ベA)
BASIC Block 6291457ー>{}Block 6291458ー>IFBlock6291459‑>{} Block 6291460
→
WHILE Block 6291461‑>{} Block 6291469expr = k=i++ + k at # 1 0
BASIC Block 6291456
→
IF Block 6291459 ‑>{} Block 6291460‑>WHlLE Block 6291461 ‑>{} Block 6291469←‑(B)変数 k の出現とブロック構造('T he2 ‑ t h o b j e c t o f i d e n t i f i e r " k " )
int mainO{' compound block 6291469 int i=O,j, k=O;
↓while block 6291461
while (k<1 OO){園compoundblock 6291460
↓ifblock 6291459 if(i<= 10)
↓basic block 6291456 k=i++ + k; +‑(B)
else{・compoundblock 6291458
↓basic block 6291457 i = i ‑ α1
ド k‑10;