gdb 사용법 Debugging Debug라는말은 bug를없앤다는말이다. Bug란, 컴퓨터프로그램상의논리적오류를말하며, 이것을찾아해결하는과정이바로, debugging이다. 초기컴퓨터들은실제벌레가컴퓨터에들어가서오작동을일으키는경우가있었다고하며, 여기서 debug 이라는말이나왔다한다. Debugging을하는가장원초적방법은프로그램소스를눈으로따라가며, 머리로실행시켜논리적오류를찾아내는것이다. 이것은프로그래머로하여금정말많은에너지를소비하게하며, 자신이작성한프로그램인경우선입견으로인해오류를찾아내기힘든경우가많다. Debugging에컴퓨터의도움을받는가장단순한방법은프로그램의중간중간에실행상태를출력하도록하는것이다. 이렇게함으로써변수에잘못된값이들어가는지여부를사람이직접계산하는것보다좀더쉽게알수있다. Debugging 과정에컴퓨터의도움을받는가장강력한방법은바로 debugging tool을이용하는것이다. Debugging tool들은프로그램이실행중일때, 변수들의값이나수행되는 statement을보여주며, 필요에따라변수값을변경하여실험을해볼수있도록해준다. gdb GDB 같은디버거의목적은다른프로그램수행중에그프로그램내부에서무슨일이일어나고있는지보여주거나프로그램이고장났을때무슨일이일어나고있는지보여주는것이다. gdb 로 C, C++, Modula-2 로짠프로그램을디버그할수있다. 버그를잡는걸돕기위해 gdb 는다음과같은작업들을가능하게한다. 1. 프로그램의행동에영향을줄수있는각종조건을설정한후, 프로그램을시작한다. 2. 특정조건을만나면프로그램을정지시킨다. 3. 프로그램이정지됐을때무슨일이일어났는지검사한다. 4. 프로그램내부설정을바꾸어서버그를수정함으로써다른버그를계속찾아나간다. Starting gdb gdb를시작하는방법은 shell prompt에서단순히 gdb 라고치는것이다. 하지만, 일반적으로는뒤에인자로실행파일을주게되며필요에다라 core 파일이나 process id를주기도한다.
$ gdb [prog] [core pid] Debugging하고자하는실행파일은 gcc에서 g 옵션을주어 compile함으로써 gdb가필요로하는부가정보들이추가된것을사용해야제대로 debugging을수행할수있다. core파일은프로그램이비정상적으로종료될때, 그때의시스템의내부상태를그대로저장해놓은것으로, 이파일을인자로주면실행파일이비정상적으로종료된곳이소스코드의어느부분인지를표시해준다. 이미실행중인프로그램을 debugging하려면해당 process의 id를주면되는데, 이때주의할것은 pid와같은이름의파일이있을경우 gdb가 core파일로여기게되는점이다. 일단 gdb가실행되면 gdb prompt가표시되며, 여기에 gdb command를주어 debugging을진행할수있게된다. gdb commands list [[file:]n func] source file의내용을 10줄씩보여준다. 행번호를지정하면n번행의주변 10라인이출력된다. 함수이름을지정하면그함수의내용이출력된다. 두개의행번호를, 로분리해서쓰면첫행번호에서시작해서두번째행번호까지의소스가출력된다. help [name] name으로지정된 gdb의 command나관련정보를보여준다. break [[file:]n function] <-> d (del) 지정된 file의 n번행또는 function에 breakpoint를설정한다. clear [[file:]n function] 지정된 file의 n번행또는 function에설정된 breakpoint를제거한다. run [arglist] program을시작한다. print expr expr의값을한번보여준다. disp expr <-> undisp expr의값을실행되는동안계속보여준다. c [n] ( 또는 continue) breakpoint등에의해멈춰진프로그램의실행을계속한다. n이지정될경우, 이후 n-1번은 breakpoint는무시하고, n번째 breakpoint에걸릴때멈춘다. next [n] 멈춰진프로그램에서프로그램의다음 n(default=1) 개의문장을실행하고다음번에실행할문장을출력한다. 함수일경우함수전체를실행한다.
step [n] 멈춰진프로그램에서프로그램의다음 n(default=1) 개의문장을실행하고다음번에실행할문장을출력한다. 함수일경우, 함수내부로들어가한문장씩실행한다. bt ( 또는 backtrace) program에서 function들이불린순서의 program stack을보여준다. up 현재의함수를호출한함수를보여준다. down 현재의함수가호출한함수를보여준다. ret ( 또는 return) 현재함수를반환하며빠져나간다. quit gdb를종료한다. xdbx
실행예제 자신의 submit directory에복사되어있는 bugshome.c 파일을 gdb를사용하여 debugging해보자. 이프로그램은 factorial과 power를계산해주는함수를구현하고이를사용하는프로그램이다. 먼저 g option으로 gcc를사용해컴파일한후, 일단실행시켜보면대충무엇이문제인지를보게된다. 물론눈으로따라가보아도쉽게버그를알아낼수있을정도의단순한 code 이지만, 우리의목적은 gdb를사용하는것이라는것을기억하자. 우선, power함수에서결과가나오지않으므로 power함수를 breakpoint로지정하여시작해보자. shell/tmt21 ~/tmp/bugshome {217} gdb a.out GNU gdb 5.0 Copyright 2000 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "hppa2.0-hp-hpux10.20"... (gdb) break power Breakpoint 1 at 0x32a8: file bugshome.c, line 16. (gdb) run Starting program: /afs/postech.ac.kr/home/std/tmt21/tmp/bugshome/a.out [NOTE] Your password will expire 119 days later. warning: Unable to find d_pid symbol in object file. warning: Suggest linking with /opt/langtools/lib/end.o. warning: GDB will be unable to track shl_load/shl_unload calls 11! = 39916800 This is f3(). Breakpoint 1, power (b=11, e=7) at bugshome.c:16 Breakpoint 1, power (b=11, e=6) at bugshome.c:16 3 Will ignore next 2 crossings of breakpoint 1. Breakpoint 1, power (b=11, e=3) at bugshome.c:16 Breakpoint 1, power (b=11, e=2) at bugshome.c:16 Breakpoint 1, power (b=11, e=1) at bugshome.c:16 Breakpoint 1, power (b=11, e=0) at bugshome.c:16 (gdb) ret 1 Make power return now? (y or n) y #0 0x32c0 in power (b=11, e=1)
at bugshome.c:16 (gdb) l 11 } 12 13 /* returns b^e, e>=0 */ 14 int power(int b, int e) 15 { 17 } 18 19 void f3() 20 { (gdb) l 21 printf("this is f3().\n"); 22 } 23 24 void f2() 25 { 26 f3(); 27 printf("11^7 = %d\n", power(11, 7)); 28 } 29 30 void f1() (gdb) break 28 Breakpoint 2 at 0x3388: file bugshome.c, line 28. 11^7 = 19487171 Breakpoint 2, f2 () at bugshome.c:28 28 } (gdb) n f1 () at bugshome.c:34 34 } (gdb) n main () at bugshome.c:40
40 printf("0! = %d\n", factorial(0)); (gdb) s factorial (n=0) at bugshome.c:7 7 if(n == 1) (gdb) l 2 #include <stdlib.h> 3 4 /* returns n * (n-1) *... * 1 */ 5 int factorial(int n) 6 { 7 if(n == 1) 8 return 1; 9 10 return n * factorial(n - 1); 11 } (gdb) ret 1 Make factorial return now? (y or n) y #0 0x342c in main () at bugshome.c:40 40 printf("0! = %d\n", factorial(0)); 0! = 1 Program exited normally. (gdb) quit References http://www.delorie.com/gnu/docs/gdb/gdb_toc.html http://sources.redhat.com/gdb/ http://www.cs.umd.edu/class/sum2002/cmsc420/gdb.html