Upload
hidi
View
63
Download
0
Embed Size (px)
DESCRIPTION
プログラム変更支援を目的とした コードクローン情報付加手法の提案と実装. 井上研究室 佐々木 亨. 研究の背景 . コードクローンとは ソースコード中に存在するコード片で、同形のコード片が他に存在するもの コピー&ペーストによるプログラム再利用などで生じる ソフトウェア保守を困難にする あるコード片にバグがあると、そのコードクローン全てについて修正の検討をしなければならない 機能を追加する場合も同様のことが言える. C1. C2. C3. C4. C5. クローンクラス. クローンクラス 同形のコードクローンの集合 例. クローンクラス1 - PowerPoint PPT Presentation
Citation preview
2004/2/26 特別研究報告会 1
プログラム変更支援を目的としたコードクローン情報付加手法の提案と実装
井上研究室佐々木 亨
2004/2/26 特別研究報告会 2
研究の背景 コードクローンとは
ソースコード中に存在するコード片で、同形のコード片が他に存在するもの
コピー&ペーストによるプログラム再利用などで生じる
ソフトウェア保守を困難にする あるコード片にバグがあると、そのコードクローン
全てについて修正の検討をしなければならない 機能を追加する場合も同様のことが言える
2004/2/26 特別研究報告会 3
クローンクラス クローンクラス 同形のコードクローンの
集合 例 C1
C5
C4
C3
C2
クローンクラス1{C1,C4,C5}
クローンクラス 2{C2,C3}
2004/2/26 特別研究報告会 4
コードクローン検出ツール CCFinder
ソースコードを字句解析してトークンの列に分解してから、トークン単位で直接比較することによりクローンを検出
数百万行規模のシステムにも実用時間で解析可能
実用的に意味のないクローンを検出しない
さまざまな企業のソフトウェアにも適用している
2004/2/26 特別研究報告会 5
CCFinder の出力#begin{file description}0 1475 3429 /home/test/test1.c1 3213 9669 /home/test/test2.c2 3584 11420 /home/test/test3.c
:#end{file description}
#begin{clone}#begin{set}0 1250,3,2811 1258,17,28530 1260,3,2861 1268,13,29031 2962,3,8913 2970,10,8955#end{set}#begin{set}1 49,1,66 55,41,1202 62,1,93 68,39,1472 75,1,159 81,37,213#end{set}
::
#end{clone}
解析対象のファイル群の情報
クローンクラス情報
ファイルの ID ・ファイル行数・ファイルパスなどからなる
クローンクラスID1 のファイルの 49 行目から 55 行目ID2 のファイルの 62 行目から 68 行目ID2 のファイルの 75 行目から 81 行目
2004/2/26 特別研究報告会 6
クローン情報を用いてソースコードを修正する際の問題点 コードクローンに対する機能追加・修正中
にクローン情報とソースコードで行番号のずれが生じる
対処法 行番号のずれを意識しながら作業する
効率が悪い 修正箇所を間違える可能性
2004/2/26 特別研究報告会 7
研究の目的 コードクローンに対する機能追加・修正中
に行番号のずれを意識せずに作業する コードクローンの位置情報を、コメントと
してソースコードに埋め込む手法の提案とツールの実装を行う
2004/2/26 特別研究報告会 8
コードクローン情報の追加(コメントの利用)
基本方針 クローンクラスごとに割り付けた ID を利用する クローンクラスに含まれる全行にコメントを追
加する コメントの形式
クローンクラスの先頭行は“ //@$ クローンクラスの ID@”
先頭行以外は“ //@ クローンクラスの ID@” ある行が 2 つ以上のクローンクラスに属している場
合はコンマで区切る
2004/2/26 特別研究報告会 9
コメント追加例クローンクラス 1#begin{set} 1 30,1,45 33,1,521 40,1,58 43,1,651 83,1,102 86,1,109#end{set}
クローンクラス 2#begin{set} 1 30,1,45 34,1,551 83,1,102 87,1,112#end{set}
30: while(a>10){31: b=b+a; 32: a=a+1;33: }34: sum = a;
40: while(c>10){41: d=d+c;42: c=c+1;43: }
83: while(e>10){84: f=f+e;85: e=e+1;86: }87: sum = e;
//@$1@//@1@ //@1@//@1@
//@$1@//@1@//@1@//@1@
//@$1@//@1@//@1@//@1@
//@$1@,@$2@//@1@,@2@//@1@,@2@//@1@,@2@//@2@
//@$1@//@1@//@1@//@1@
//@$1@,@$2@//@1@,@2@//@1@,@2@//@1@,@2@//@2@
2004/2/26 特別研究報告会 10
デバッグへの利用手順1.あるバグを発見する
2.ソースコードにクローン情報の コメントを付加する
3.バグを修正する4.修正部分のコメントを調べる
5.コメント中のクローンクラスの ID を利用してクローンクラスの 先頭行を見つける
6.他の修正箇所を見つける7.同様の修正を行う8.不要になったコメントを除去する
while(a > 10){ b=b+a; a=a+1; }Sum = a; : while(c > 10){ d=d+c; c=c+1; } :
while(e > 10){ f=f+e; e=e+1; }Sum = e;
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
//@$1@ //@1@ //@1@ //@1@
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c > 10){ d=d+c; c=c+1; } :
while(e > 10){ f=f+e; e=e+1; }Sum = e;
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
//@$1@ //@1@ //@1@ //@1@
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c < 10){ d=d+c; c=c+1; } :
while(e < 10){ f=f+e; e=e+1; }Sum = e;
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
//@$1@ //@1@ //@1@ //@1@
//@$1@,@$2@
//@1@,@2@ //@1@,@2@ //@1@,@2@ //@2@
while(a < 10){ b=b+a; a=a+1; }Sum = a; : while(c < 10){ d=d+c; c=c+1; } :
while(e < 10){ f=f+e; e=e+1; }Sum = e;
while 文の条件が間違っている
2004/2/26 特別研究報告会 11
ツールの機能 コメント追加機能
コメントにはクローンクラスの ID を利用 コメントはクローンクラスに含まれる全行に追加 追加はオリジナルファイルに行わず、編集用の一時的なファイルに行
う クローンクラス検索機能
クローンクラスを指定し、そのコメントがあるファイル情報等を検索・表示
一時ファイル編集機能 コメント追加後、ファイル編集のためにファイルを選択して開く
コメント除去機能 不要となったコメントを、クローンクラスの ID を指定して除去する すべてのコメントを一括して除去する
一時ファイル書き戻し機能 編集用の一時的なファイルの変更をオリジナルファイルに反映させる
2004/2/26 特別研究報告会 12
適用実験 日本語入力システム「かんな」 (http://canna.so
urceforge.jp) のバージョン 3.6 と 3.6p1 の間でのセキュリティ問題の修正に対して擬似的なデバッグを行うことで適用した ソースコードは C 言語で記述、 92 ファイル、約 9 万
行 この修正は、バッファのオーバーフローを調べる処理
の追加で、全20箇所にほぼ同じ修正を行っている 具体的な追加コードは if(Request.type7.datalen!=SIZEOFSHORT*3) return (-1); 等
実行環境 FreeBSD Pentium4 1.5GHz 512MB
2004/2/26 特別研究報告会 13
具体例(修正前の「かんな」ソースコード)
下図の 2405 行目の直前にオーバーフローの検査処理を追加する
2399 static 2400 ProcWideReq7(buf) 2401 BYTE *buf ; 2402 { 2403 ir_debug( Dmsg(10, "ProcWideReq7 start!!\n")); 2404 2405 buf += HEADER_SIZE; Request.type7.context = S2TOS(buf); 2406 buf += SIZEOFSHORT; Request.type7.number = S2TOS(buf); 2407 buf += SIZEOFSHORT; Request.type7.yomilen = (short)S2TOS(buf); 2408 ir_debug( Dmsg(10, "req->context =%d\n", Request.type7.context)); 2409 ir_debug( Dmsg(10, "req->number =%d\n", Request.type7.number)); 2410 ir_debug( Dmsg(10, "req->yomilen =%d\n", Request.type7.yomilen)); 2411 2412 return( 0 ) ; 2413 }
2004/2/26 特別研究報告会 14
#begin{set} 0.91 2367,1,7452 2375,24,74830.91 2383,1,7519 2391,24,75500.91 2399,1,7586 2407,24,76170.91 2415,1,7657 2423,24,76880.91 2433,1,7739 2441,24,7770 :#end{set}#begin{set} 0.91 2376,5,7488 2381,2,75180.91 2392,5,7555 2397,2,75850.91 2408,5,7626 2413,2,76560.91 2426,5,7708 2431,2,77380.91 2444,5,7790 2449,2,7820 :#end{set}#begin{set} 0.91 2399,1,7586 2407,50,76190.91 2587,1,8410 2595,51,8443 :#end{set}
#begin{set} 0.91 2367,1,7452 2375,24,74830.91 2383,1,7519 2391,24,75500.91 2399,1,7586 2407,24,76170.91 2415,1,7657 2423,24,76880.91 2433,1,7739 2441,24,7770 :#end{set}#begin{set} 0.91 2376,5,7488 2381,2,75180.91 2392,5,7555 2397,2,75850.91 2408,5,7626 2413,2,76560.91 2426,5,7708 2431,2,77380.91 2444,5,7790 2449,2,7820 :#end{set}#begin{set} 0.91 2399,1,7586 2407,50,76190.91 2587,1,8410 2595,51,8443 :#end{set}
2405 行目に追加したためソースコードとコードクローン情報の間で行番号が 2行ずつずれている
ツールを利用しない場合 - コードクローン位置情報のずれ
2420行目に同様の 2行分の修正を行ったとする
2420行目に同様の 2行分の修正を行ったとする
赤い部分のずれは 2 行青い部分のずれは 4 行
この修正例において全部で20箇所 101行もの処理を追
加
この修正例において全部で20箇所 101行もの処理を追
加
行番号の増減を意識しながら作業するのは困難
#begin{set} 0.91 2367,1,7452 2375,24,74830.91 2383,1,7519 2391,24,75500.91 2399,1,7586 2407,24,76170.91 2415,1,7657 2423,24,76880.91 2433,1,7739 2441,24,7770 :#end{set}#begin{set} 0.91 2376,5,7488 2381,2,75180.91 2392,5,7555 2397,2,75850.91 2408,5,7626 2413,2,76560.91 2426,5,7708 2431,2,77380.91 2444,5,7790 2449,2,7820 :#end{set}#begin{set} 0.91 2399,1,7586 2407,50,76190.91 2587,1,8410 2595,51,8443 :#end{set}
「かんな」バージョン 3.6 のコードクローン情報
2004/2/26 特別研究報告会 15
2399 static //@$1311@,@$1318@2400 ProcWideReq7(buf) //@1311@,@1318@2401 BYTE *buf ; //@1311@,@1318@2402 { //@1311@,@1318@2403 ir_debug( Dmsg(10, "ProcWideReq7 start!!\n")); //@1311@,@1318@2404 //@1311@,@1318@2405 if(Request.type7.datalen!=SIZEOFSHORT*3)2406 return (-1);2407 buf += HEADER_SIZE; Request.type7.context = S2TOS(buf); //@1311@,@1318@2408 buf += SIZEOFSHORT; Request.type7.number = S2TOS(buf); //@1311@,@1318@2409 buf += SIZEOFSHORT; Request.type7.yomilen = (short)S2TOS(buf); //@1311@,@13
18@2410 ir_debug( Dmsg(10, "req->context =%d\n", Request.type7.context)); //@$1317
@2411 ir_debug( Dmsg(10, “req->number =%d\n", Request.type7.number)); //@1317@2412 ir_debug( Dmsg(10, "req->yomilen =%d\n", Request.type7.yomilen)); //@1317@2413 //@1317@2414 return( 0 ) ; //@1317@2415 } //@1317@
追加処理
この部分のコメントを見ればクローンクラス 1311 と 1318 に関して同様の修正の検討をすればいいとわかる(実際に 1311 に対して修正を行っていた)
行番号のずれを意識することなく作業することができる
ツールを利用する場合 - コメント付加後に追加
コメント追加 約 5 秒コメント全消去 約 3 秒一時ファイル書き戻し
約 3 秒
クローンクラス検索 1 秒未満
2004/2/26 特別研究報告会 16
まとめと今後の課題 まとめ
プログラム変更作業を支援するための、コードクローン情報付加手法の提案、ツールの試作をし、「かんな」のバグ修正作業に適用した
今後の課題 実際のソフトウェア開発・保守現場での評価
2004/2/26 特別研究報告会 17
終わり
2004/2/26 特別研究報告会 18
これ以降は発表に入れないスライド
2004/2/26 特別研究報告会 19
定義 完全性
修正が必要な箇所のうち実際に検出された割合 効率性
検出されたうち実際に修正箇所である割合 検出された
ある修正箇所を特定したときに、その箇所にあるコメント内のクローンクラス ID をたどってたどり着ける箇所
2004/2/26 特別研究報告会 20
評価内容 本ツールにおける「検出され
た数」の定義 修正箇所(関数単位)を節点
として、同じクローン ID をもつ他の節点に辺をつなぐ
ある節点から到達することのできる節点の総数
//CL1
//CL1,2
//CL2
//CL3
//CL2,3
総修正箇所は 4 箇所検出された箇所は 5 箇所
検出された修正箇所は 3 箇所完全性 (4 箇所中 3 箇所 ) 75%効率性 (5 箇所中 3 箇所 ) 60%
2004/2/26 特別研究報告会 21
評価結果grep 本ツール
総修正箇所 20 箇所 20 箇所
検出された箇所 61 箇所 15 箇所
検出された箇所中の修正箇所
19 箇所 15 箇所
完全性 95% 75%
効率性 34% 100%
f値 0.5 0.86
f 値を見ると、本ツールは grep より有効である
効率性完全性効率性完全性2
値=f
2004/2/26 特別研究報告会 22
補足実験 CCFinder の最小一致トークン数を変化させた
トークン数 完全性 効率性 コメント数50 13% 100% 0.5個40 17% 100% 1.0個30 75% 100% 4.2個20 90% 100% 11個10 100% 5% 未満 30個
• コメント数 : 1修正箇所中のコメント数
2004/2/26 特別研究報告会 23
grep で検出されなかった唯一のクローン
staticProcWideReq1(buf)BYTE *buf ;/* ARGSUSED */{ ir_debug( Dmsg(10, "ProcWideReq1 start!!\n") ); return( 0 ) ;}
・この部分を検索キーとすれば grep でも検出されるが、これだと他にも数多く検出される ( 135 行一致する f 値は 0.26 )
このように grep などのコード片を指定して検索する場合は利用者の能力に
よって検索結果に差が出るしかし、
本ツールではその必要がないためその心配がない
2004/2/26 特別研究報告会 24
1311 は修正箇所で 1318 は修正しなくてよかったのはなぜ?
クローンクラス 1311
クローンクラス 1312 クローンクラス 1318
実際には 1312 に対して修正が行われていたつまり、 1311 に修正を行ったというより、1312 に対して修正を行っていた
2004/2/26 特別研究報告会 25
編集用の一時ファイルの作成方法 対象のファイル群のパスの深さの最小値から、ディレ
クトリファイル階層を実現する 1 /home/Canna36/cmd/wtoc/wtoc.c 2 /home/Canna36/dic/ideo/pubdic/pod.c 3 /home/Canna36/doc/man/guide/tex/cannaindex.c 4 /home/Canna36/misc/is.c 5 /home/Canna36/sample/sample.cだと 4 と 5 が深さ 4 でパスが最も短い。深さ 3 番目からをこちらで新たに
作ったディレクトリ Append_Comment_Files 中に再現する 1’ / Append_Comment_Files /cmd/wtoc/wtoc.c 2’ / Append_Comment_Files /dic/ideo/pubdic/pod.c 3’ / Append_Comment_Files /man/guide/tex/cannaindex.c 4’ / Append_Comment_Files /misc/is.c 5’ / Append_Comment_Files /sample/sample.cとなる。
2004/2/26 特別研究報告会 26
既存のコードクローン検出手法(1/2)
Baker の手法 行単位でソースコードを比較してコードクローンを検
出Baxter らの手法
C 言語のソースファイルを入力,構文解析して,解析木 ( の部分木 ) を比較する
[Baker1995] B. S. Baker: “On finding Duplication and Near-Duplication in Large Software System,” Proc. Second IEEE Working Conf. Reverse Eng., pp. 86-95, Tronto, Canada (Jul., 1995).[Baxter1998] I. D. Baxter, A. Yahin, L. Moura, M. Sant’Anna, and L. Bier: “Clone Detection Using Abstract Syntax Trees,” Proc. of ICSM ’98, pp. 368-377, Bethesda, Maryland (Nov., 1998).
2004/2/26 特別研究報告会 27
既存のコードクローン検出手法(2/2)
Merlo らの手法 手続き(メソッドや関数)の特徴メトリクスを
比較して,計測値が似ていればコードクローンであると判定する
[Balazinska1999] M. Balazinska, E. Merlo, M. Dagenais, B. Lague, and K.A. Kontogiannis, "Measuring Clone Based Reengineering Opportunities", Proc. 6th IEEE Int'l Symposium on Software Metrics (METRICS '99), pp. 292-303, Boca Raton, Florida, Nov. 1999.
2004/2/26 特別研究報告会 28
CCFinder: コードクローン検出ツール
ソースコードを字句解析してトークンの列に直してからコードクローン検出を行う (浅い)文法知識に基づいたソースコード変形
クラススコープや名前空間による複雑な名前の正規化を行う
初期化テーブルを取り除く モジュールの区切りを認識する
言語依存部分を取り替えることで,さまざまなプログラミング言語に対応
2004/2/26 特別研究報告会 29
コードクローン検出手順(1) ソースコードを入力し,トークンの列にす
る(2) 変形ルールにより,トークン列を変形する(3) パラメータ置換を行う(4) マッチングアルゴリズムによりコードクロ
ーンを検出する(5) コードクローンの位置 ( ファイル,行 , カ
ラム ) を出力する
2004/2/26 特別研究報告会 30
1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }
例題ソースコード
2004/2/26 特別研究報告会 31
1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) { 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. } 9. System.out.println("sum = " + sum);10. }11. static void goo(String [] a) throws RESyntaxException {12. RE exp = new RE("[0-9,]+");13. int sum = 0;14. for (int i = 0; i < a.length; ++i) {15. if (exp.match(a[i]))16. sum += parseNumber(exp.getParen(0));17. }18. System.out.println("sum = " + sum);19. }
4-6 行目と
13-15 行目,
8-10 行目と
17-19 行目
2004/2/26 特別研究報告会 32
クローン
1. static void foo() throws RESyntaxException { 2. String a[] = new String [] { "123,400", "abc", "orange 100" }; 3. org.apache.regexp.RE pat = new org.apache.regexp.RE("[0-9,]+"); 4. int sum = 0; 5. for (int i = 0; i < a.length; ++i) 6. if (pat.match(a[i])) 7. sum += Sample.parseNumber(pat.getParen(0)); 8. System.out.println("sum = " + sum); 9. }10. static void goo(String [] a) throws RESyntaxException {11. RE exp = new RE("[0-9,]+");12. int sum = 0;13. for (int i = 0; i < a.length; ++i)14. if (exp.match(a[i]))15. sum += parseNumber(exp.getParen(0));16. System.out.println("sum = " + sum);17. }
2004/2/26 特別研究報告会 33
修正のたびにコードクローンの位置情報を更新すると‥
クローンペア
修正する
クローンでなくなる
検出されなくなる
2004/2/26 特別研究報告会 34
実装 Java で実装 動作環境 FreeBSD
メニューバー
ステータスバー