GDB利用法 第3回

前回(GDB利用法第2回)前々回(GDB利用法第1回)に続き今回は、

デバッグではなくテストフェーズのツールとしての利用法の簡単な例を記述したものです。

この辺は今後もう少し掘り下げていきたいと思っていますが、

まずは触りとして見て頂ければと思います。

 

 

C/C++言語におけるgdb駆動開発

gdbはデバッガであり、基本的にはプログラムのデバッグに利用される。
gdbはソースを変更することなくプログラムの状態を変更し実行することができ、それらの機能を条件を
決めて自動的に実行することも可能になっている。
この機能を拡張的に利用することで、gdbは単なるデバッガではなく、「自動テストツール」として
利用することができる。
このことを意識しながら開発にgdbを利用することで試験の効率が向上し、プログラムの精度も向上
させることが可能になる。

gdbとカバレジ機能を用いた関数の試験

ソースコードにmain関数を含まない関数の試験

ソースコードにGDB_TEST_MAIN(任意)でくくったifdef中に試験用のコードを予め入れておく。
基本的にスケルトンなmain関数だけでかまわない。
サンプルではシンボル情報を利用できるようにシンボル付のモジュールを作成している。
このときモジュールの作成順に注意すること。(試験するモジュールを後)
ただし最終的に -coverage をはずして試験する必要があるため、-coverage を付けたテスト時は
シンボル情報付のモジュールだけで十分である。(この場合はtest.txtのsymbol-fileの行は不要)
mainを含むソースコードの場合はそのまま試験を行えば良い。
試験を最初から繰り返す場合は r で先頭から実行する。(このときは前に設定した内容は有効)

$gcc -g compfunc.c -DGDB_TEST_MAIN -coverage -o a.gdb
$gcc compfunc.c -DGDB_TEST_MAIN -coverage -o a.out
$gdb -q a.out -x test.txt
(no debugging symbols found)
Breakpoint 1 at 0x80488d2: file compfunc.c, line 8.

Breakpoint 1, main () at compfunc.c:8
8 {
test1 OK
test2 OK
test3 NG

Program exited normally.
$gcov compfunc.gcda
File ‘compfunc.c’
Lines executed:100.00% of 8
compfunc.c:creating ‘compfunc.c.gcov’

$cat compfunc.c.gcov
-: 0:Source:compfunc.c
-: 0:Graph:compfunc.gcno
-: 0:Data:compfunc.gcda
-: 0:Runs:1
-: 0:Programs:1
-: 1:#include <stdio.h>
-: 2:typedef struct{
-: 3:int a,b;
-: 4:} COMP;
-: 5:
-: 6:#ifdef GDB_TEST_MAIN
-: 7:int main(int argc, char *argv[])
1: 8:{
1: 9: return 0;
-: 10:}
-: 11:#endif
-: 12:
-: 13:char compfunc(COMP no)
3: 14:{
3: 15: if(no.a>no.b){
1: 16: return ‘a’;
-: 17: }
2: 18: if(no.a<no.b){
1: 19: return ‘b’;
-: 20: }
1: 21: return ‘ ‘;
-: 22:}
-: 23:
$

○compfunc.cの内容
#include <stdio.h>
typedef struct{
int a,b;
} COMP;

#ifdef GDB_TEST_MAIN
int main(int argc, char *argv[])
{
return 0;
}
#endif

char compfunc(COMP no)
{
if(no.a>no.b){
return ‘a’;
}
if(no.a<no.b){
return ‘b’;
}
return ‘ ‘;
}

○test.txtの内容
symbol-file a.gdb
b main
r
#—————————–
echo test1
set $a = (COMP){2,1}
set $b = compfunc($a)
if $b==’a’
echo \ OK \n
else
echo \ NG \n
end
#—————————–
echo test2
set $a = (COMP){1,2}
set $b = compfunc($a)
if $b==’b’
echo \ OK \n
else
echo \ NG \n
end
#—————————–
echo test3
set $a = (COMP){1,1}
set $b = compfunc($a)
if $b==’b’
echo \ OK \n
else
echo \ NG \n
end
c
q
y

gdbを利用した動的関数を利用する試験

$gcc -shared -o testlib.so testlib.c
$gcc sample.c testlib.so
$export LD_LIBRARY_PATH=(testlib.soのパス)
$gdb -x baseFile.txt ./a.out

自動で実行が続く

^C (Ctrl-C) で中断
(gdb) q   (c なら再開)
The program is running. Quit anyway (and detach it)? (y or n) y
$

○sample.c の内容
#include <stdio.h>

int CheckNum;

function1(int *no)
{
printf(“no=%d\n”,*no);
(*no)++;
}

main()
{
CheckNum = 0;
while(1){
function1(&CheckNum);
sleep(1);
if(CheckNum>10) CheckNum = 0;
}
}

○testlib.c の内容
void resetCheckNum(int *no)
{
*no = 0;
}

○baseFile.txt の内容
set pagination off
set logging file baseFile.log
watch CheckNum
source watch1.txt
set logging on
run

○watch1.txt の内容
command 1
where
if CheckNum==3
call resetCheckNum(&CheckNum)
end
echo CheckNum\n
p CheckNum
c
end

 

次回は検討中です

Pocket