본문 바로가기

4. 기술창고, Warehouse

GDB 사용법

GDB 사용법

 

Debugging이란

Debugging bug, 컴퓨터 프로그램 상의 논리적 오류를 찾아 해결하는 과정이다.

 

Debugging 방법

l        프로그램 소스를 눈으로 따라가며머리로 실행시켜 논리적 오류를 찾아낸다이것은 프로그래머로 하여금 정말 많은 에너지를 소비하게 하며자신이 작성한 프로그램인 경우 선입견으로 인해 오류를 찾아내기 힘든 경우가 많다.

l        프로그램의 중간 중간에 printf 사용하여 실행 상태를 출력하도록 한다이렇게 함으로써 변수에 잘못된 값이 들어가는지 여부를사람이 직접 계산하는 것보다   쉽게   있다.

l        Debugging tool (gdbdbxxdbx ) 이용한다. Debugging tool들은 프로그램이 실행 중일 변수들의 값이나 수행되는 statement보여주며필요에 따라 변수 값을 변경하여 실험을    있도록 해준다.

 

gdb (GNU Debugger)

gdb C, C++, Modula-2 구현된 프로그램을 디버그할  있는 도구이다. 버그를 잡는  돕기 위해 gdb 다음과 같은 작업들을 가능하게 한다.
l        프로그램의 행동에 영향을   있는 각종 조건을 설정한 , 프로그램을 시작한다.
l        특정 조건을 만나면 프로그램을 정지시킨다.
l        프로그램이 정지됐을  무슨 일이 일어났는지 검사한다.
l        프로그램 내부 설정을 바꾸어서 버그를 수정함으로써 다른 버그를 계속 찾아나간다.

 

gdb 실행

gdb [prog [core|procID]]

l         prog디버깅할 프로그램

l         core: 프로그램 실행 중에 “segmentation fault” 등의 오류에 의해 비정상적으로 종료할  생성되는 파일로그때의 시스템의 내부상태를 그대로 저장해 놓은 것이다 파일을 인자로 주면 실행파일이 비정상적으로 종료된 곳이 소스코드의 어느 부분인지를표시해 준다.

l         procID이미 실행중인 프로그램을 debugging하려면 해당 process id (PID) 주면 되는데  주의  것은 PID 같은 이름의 파일이 있을 경우 gdb core파일로 여기게 되는 점이다.

주의Debugging하고자 하는 실행파일은 gcc에서 –g 옵션을 주어 compile함으로써 gdb 필요로 하는 부가 정보들이 추가된 것을 사용해야제대로 debugging 수행할  있다.

 

gdb 명령어

gdb 실행하여 gdb prompt ‘(gdb) ’ 표시된 상태에서 gdb 명령어를 사용하여 디버깅을 진행한다.

참고: class command 축약형도 지원된다. (, ‘run’명령어를 축약형 ‘r’ 대신할  있다.)

l         도움말 (help)

help [class|command]

도움말명령어 분류 목록 출력해당 class 속한 명령어 목록 표시해당 command 대한 도움말 표시

l         프로그램 수행 (running)

kill

디버깅 중인 프로그램의 실행을 강제로 종료시킨다.

run [args]

디버깅할 프로그램의 수행을 시작한다프로그램 실행에 필요한 argument (args) 지정할  있다args 지정하지 않으면 바로 이전의 run실행이나 “set args명령에 의해 미리 주어진 argument 사용한다입출력 방향 재지정 (“>”, “<”, “>>”) 사용할  있다.

set args [args]

프로그램이 시작될 디버깅할 프로그램에 전달할 argument 설정한다.

next [n]

멈춰진 프로그램에서 프로그램의 다음 n(default=1)개의 문장을 수행한  멈춘다함수일 경우함수 전체를 수행한다.

step [n]

멈춰진 프로그램에서 프로그램의 다음 n(default=1)개의 문장을 수행한  멈춘다함수일 경우함수 내부로 들어가  문장씩 수행한다.

continue [n]

시그널(Ctrl-C)이나 breakpoint 등에 의해 멈춰진 프로그램의 수행을 계속한다n 지정될 경우이후 n-1번의 breakpoint 무시하고,n번째 breakpoint에서 수행을 멈춘다.

until [[file:]n|function]

프로그램이 현재 라인보다  라인이나 또는 지정된 라인이나 어드레스 또는 함수에 도달할 때까지 수행한다(break 명령과 동일한argument). 또한현재 stack frame 빠져나올 때도 멈춘다. loop 지날 첫번째 loop수행에서는 next명령과 동일하지만 두번째loop수행부터는  loop 벗어날 때까지 멈추지 않는다.

l         스택 검사 (stack)

스택은 스택 프레임으로 구성된다gdb 스택 프레임에 번호를 지정하는데가장 안쪽에 있는(현재 실행중인프레임에 대해 0번부터 번호를 부여한다gdb 항상  프레임을 선택된 프레임으로 간주하며선택된 프레임에 대하여 변수  보기가 이루어진다아래 명령어들에서 숫자나 어드레스를 사용하여 다른 프레임을 지정할 수도 있다.

bt (또는 backtrace 또는 where[[-]N]

모든 스택 프레임이나 가장 안쪽에 있는 N개의 프레임에 대한 backtrace 출력한다. argument 음수(-N) 가장 바깥쪽에 있는N개의 프레임을 출력한다.

frame [N]

스택 프레임을 선택하고 출력한다N 선택할 프레임 번호(혹은 프레임의 주소) 가리킨다. Argument 없으면 현재 선택된 프레임을 출력한다.

up [N]

현재 선택된 프레임을 호출한 스택 프레임 (caller) 선택하고 출력한다N  개의 프레임 위로 올라가야 할지를 말해준다.

down [N]

현재 선택된 프레임에 의해 호출된 스택 프레임 (callee) 선택하고 출력한다N  개의 프레임 아래로 내려가야 할지를 말해준다.

return [rvalue]

선택된 스택 프레임으로 하여금 호출자 (caller)에게로 리턴하게 한다실행은 현재 선택된 것보다 위에 있는 프레임 (caller)에서 계속될 것이다rvalue 리턴 값을 지정한다.

set variable [variable] = [exp]

[variable] 값을 [exp] 계산 결과로 대치한다. set variable 대신 set 써도 된다.

 

l         데이터 검사 (data)

whatis EXP

expression EXP data 타입을 출력한다.

ptype TYPE

타입 TYPE 정의를 출력한다.

print [EXP]

expression EXP 값을 출력한다EXP 사용될  있는 변수는 선택된 프레임에 있는 변수이거나 전역 변수이다.

printf  [“format string”, arg1, arg2, arg3, ..., argn]

printf 형식으로 출력한다.

display [EXP]

expression EXP 값을 프로그램이 멈출 때마다 출력한다.

delete display (또는 undisplay[N ]

프로그램이 정지할 때마다 출력되는 몇몇 expression 취소한다N 취소할 expression 번호를 지정한다. Argument 없으면 모든자동 출력 expression 취소한다.

disable display [N …]

프로그램이 정지할 때마다 출력되는 몇몇 expression disable한다N disable expression 번호를 지정한다. Argument 없으면모든 자동 출력 expression disable한다.

enable display [N …]

프로그램이 정지할 때마다 출력되는 몇몇 expression enable한다N enable expression 번호를 지정한다. Argument 없으면 모든 자동 출력 expression enable한다.

l         특정 지점에서 프로그램 정지 (breakpoints)

watch [EXP]

expression EXP 대한 watchpoint 설정한다EXP 값이 변할 때마다 프로그램의 수행을 멈춘다.

break [[file:]n|function]

특정 라인(n)이나 함수(function) breakpoint 설정한다. Argument 없으면 현재 수행 위치에 breakpoint 설정한다프로그램이 수행 중에 지정된 breakpoint 도착하면 수행을 멈춘다.

clear [[file:]n|function]

특정 라인(n)이나 함수(function) 설정된 breakpoint 제거한다. Argument 없으면 현재 수행 위치에 설정된 모든 breakpoint 제거한다.

delete [N …]

몇몇 breakpoint 자동 출력 expression 제거한다N 제거할 breakpoint 번호를 가리킨다. Argument 없으면 모든 breakpoint 제거한다.

disable [N …]

몇몇 breakpoint disable시킨다N disable breakpoint 가리킨다. Argument 없으면 모든 breakpoint disable시킨다. disablebreakpoint enable 의해 다시 동작하도록   있다.

enable [N …]

몇몇 breakpoint enable시킨다N enable breakpoint 가리킨다.

condition [ COND]

breakpoint N에서 COND true 때만 멈추도록 명시한다.

 

l         검사할 파일 (files)

cd [DIR]

작업 디렉토리를 DIR 설정한다

pwd

작업 디렉토리를 출력한다.

core-file [FILE]

FILE core dump 파일로 사용한다.

file [FILE]

FILE 디버깅할 프로그램으로 사용한다.

list [[file:]n|function][, [file:]n|function]

지정된 함수나 라인 앞뒤의 11라인을 출력한다콤마로 분리된  개의 Argument 출력할 시작 라인과  라인을 가리킨다. Argument 없으면 앞서 출력된 라인 이후의 10 라인을 출력한다. “list – 앞서 출력된 라인 이전의 10 라인을 출력한다.

l         상태 조회 (status)

info

디버깅 중인 프로그램에 대한 여러가지를 보여 주기 위한 포괄적인 명령어

info breakpoints (또는 info watchpoints[N]

설정된 breakpoint 상태를 보여준다N 특정 breakpoint 번호를 가리킨다. Argument 없으면 모든 breakpoint 상태를 보여 준다.

info args

현재 스택 프레임의 인자 변수를 보여준다.

info display

프로그램이 멈출  출력할 expression들을 보여준다.

l         지원도구 (support)

help [class|command]

도움말명령어 분류 목록 출력해당 class 속한 명령어 목록 표시해당 command 대한 도움말 표시

quit

gdb 종료한다.

make [args]

‘make’ 실행한다.

 

gdb 사용 예제

gdb 사용법을 익히기 위해 bug 있는 간단한 프로그램을 gdb 사용하여 디버깅해 보자먼저, /afs/p/class/cse/yjsuh/csed103F2004/lab/lecture_note/bug.c 각자의 디렉토리로 복사한다.

mkdir debug; cd debug

cp /afs/p/class/cse/yjsuh/csed103F2004/lab/lecture_note/bug.c ./

 

bug.c 소스 코드는 다음과 같다.

#include <stdio.h>

 

int score[5];

 

 

int sum(int cnt)

{

   int i;

   int sum;

 

   for(i = 0; i < cnti++)

      sum += score[i];

 

   return sum;

}

 

 

int main()

{

   int cnt=0;

 

   printf("input scores. input -1 to finish.\n");

   while(1)

   {

      printf("score%d? ", cnt+1);

      scanf("%d", score[cnt]);

      if(score[cnt] == -1)

         break;

      cnt++;

   }

 

   printf("%d scores read.\n", cnt);

 

   printf("--- result ---\n");

   printf("sum: %d   avg: %d\n", sum(cnt), sum(cnt)/cnt);

 

   return 0;

}

 

 소스 코드는 임의의 개수의 점수를 입력 받아 총점과 평균을 출력해 주는 프로그램이다이를 컴파일하여 실행 해보면 segmentation fault 오류가 나며 core파일이 생성되며 종료된다생성된 core 파일을 바탕으로 디버깅을 한다이때 컴파일시 –g 옵션을 써주어야 디버깅 정보를   있다굵은 글씨가 사용자가 입력한 부분이다.

 

vision/endovert ~/gdb {298} gcc -g bug.c

vision/endovert ~/gdb {299} a.out

input scores. input -1 to finish.

score1? 100

Segmentation fault (core dumped)

vision/endovert ~/gdb {300} gdb

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 "alpha-dec-osf4.0d".

(gdbfile a.out

Reading symbols from a.out...done.

(gdbcore core

Core was generated by `a.out'.

Program terminated with signal 11, Segmentation fault.

Reading symbols from /usr/shlib/libc.so...done.

#0  0x3ff800e1e4c in _doscan () from /usr/shlib/libc.so

(gdbbt

#0  0x3ff800e1e4c in _doscan () from /usr/shlib/libc.so

#1  0x3ff8018ea80 in scanf () from /usr/shlib/libc.so

#2  0x120001384 in main () at bug.c:26

(gdblist 26

21

22         printf("input scores. input -1 to finish.\n");

23         while(1)

24         {

25            printf("score%d? ", cnt+1);

26            scanf("%d", score[cnt]);

27            if(score[cnt] == -1)

28               break;

29            cnt++;

30         }

 (gdbquit

vision/endovert ~/gdb {301}

bt결과를 보면 26번째 행에서 core dump 일어난 것을   있다. 26 행을 보면 scanf 인자로 넣은 변수 score[cnt앞에 & 빠졌음을  있다고쳐서 다시 컴파일 해본다이번엔 결과값이 이상하게 나온다다시 gdb 사용하여 다시 디버깅해본다.

vision/endovert ~/gdb {303} gcc -g bug.c

vision/endovert ~/gdb {304} a.out

input scores. input -1 to finish.

score1? 100

score2? 100

score3? 100

score4? -1

3 scores read.

--- result ---

sum: 301   avg: 200

vision/endovert ~/gdb {305} 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 "alpha-dec-osf4.0d"...

(gdbbreak sum

Breakpoint 1 at 0x120001268: file bug.c, line 7.

(gdbrun

Starting program: /afs/postech.ac.kr/home/std/endovert/gdb/a.out

input scores. input -1 to finish.

score1? 50

score2? 50

score3? 50

score4? -1

3 scores read.

--- result ---

 

Breakpoint 1, sum (cnt=0) at bug.c:7

7       {

(gdbl

2

3       int score[5];

4

5

6       int sum(int cnt)

7       {

8          int i;

9          int sum;

10

11         for(i = 0; i < cnti++)

(gdbprint sum

$1 = 1

(gdbnext

11         for(i = 0; i < cnti++)

(gdbstep

12            sum += score[i];

(gdbdisplay sum

1: sum = 1

(gdbs

11         for(i = 0; i < cnti++)

1: sum = 51

(gdbs

12            sum += score[i];

1: sum = 51

(gdbs

11         for(i = 0; i < cnti++)

1: sum = 101

(gdbset sum = 100

(gdbprint sum

$2 = 100

(gdbs

12            sum += score[i];

1: sum = 100

(gdbs

11         for(i = 0; i < cnti++)

1: sum = 150

(gdbs

14         return sum;

1: sum = 150

(gdbs

15      }

1: sum = 150

(gdbinfo display

Auto-display expressions now in effect:

Num Enb Expression

1:   y  sum

(gdbdelete display 1

(gdbcontinue

Continuing.

 

Breakpoint 1, sum (cnt=3) at bug.c:7

7       {

(gdbbt

#0  sum (cnt=3) at bug.c:7

#1  0x120001414 in main () at bug.c:35

(gdbl 35

30         }

31

32         printf("%d scores read.\n", cnt);

33

34         printf("--- result ---\n");

35         printf("sum: %d   avg: %d\n", sum(cnt), sum(cnt)/cnt);

36

37         return 0;

38      }

39

(gdbs

11         for(i = 0; i < cnti++)

(gdbprint sum

$3 = 150

(gdbi

$4 = 3

(gdbs

12            sum += score[i];

(gdbprint sum

$5 = 150

(gdbprint i

$6 = 0

(gdbreturn 150

Make sum return now? (y or n) y

#0  0x120001414 in main () at bug.c:35

35         printf("sum: %d   avg: %d\n", sum(cnt), sum(cnt)/cnt);

(gdbc

Continuing.

sum: 150   avg: 50

 

Program exited normally.

(gdbinfo break

Num Type           Disp Enb Address    What

1   breakpoint     keep y   0x120001268 in sum at bug.c:7

        breakpoint already hit 2 times

(gdbdelete 1

(gdbinfo break

No breakpoints or watchpoints.

(gdbq

vision/endovert ~/gdb {306}

합을 계산하는 sum함수에 breakpoint 걸고 실행 시켜보면 초기의 sum 값이 0 아닌 다른  ( 경우 1) 나옴을   있다. sum값이 0으로 초기화 되도록 소스를 고친다.