디버깅을 할 때에 가장 많이 쓰는 전술은 printf() 문을 추가하는 방법이다.
장점
- 누구나 처음에 취할 수 있는 전술이다.
단점
- 실행파일만 있고 소스가 없다면, 혹은 소스가 있지만 새로 컴파일 할 수 없다면 이 전술을 사용할 수 없다.
- 시간이 오래 걸린다.
gdb 명령
gdb 실행 가능 파일 명령을 사용해 gdb로 응용 프로그램 디버깅을 시작한다. 먼저 gdb는 실행 파일 심볼을 로드한다. 그런 다음 프롬프트를 표시해 디버거를 사용할 수 있음을 알린다.
gdb로 프로세스 보는 방법
1. 실행중인 프로세스를 보러면 attach 명령을 사용한다. 이 명령은 프로세스를 중지한다.
2. 프로그램을 시작하려면 run 명령을 사용한다.
3. 이미 존재하는 코어 파일을 살펴, 프로세스가 충돌하거나 죽은 시점의 상태를 파악한다.
유용한 gdb 명령
명령 |
약어 |
설명 |
attach |
at |
실행 중인 프로세스에 디버거 붙임 |
backtrace |
bt |
stack trace를 출력 |
break |
b |
정지점 설정 |
clear |
|
정지점 해제 |
continue |
c |
프로그램 실행 계속 |
delete |
|
번호로 정지점 설정을 해제 |
detach |
|
현재 실행 중인 프로세스에서 디버거 뗌 |
display |
|
실행을 중단할 때마다 표현값을 출력 |
finish |
|
함수 끝까지 실행하고 함수 반환값을 표시 |
help |
|
gdb 명령어 도움말 출력 |
jump |
|
특정 주소로 분기하여 실행 계속 |
list |
|
원시코드 목록에서 다음 10줄 출력 |
next |
n |
프로그램 한단계 수행, 함수는 함수 내부로 들어가지 않음 |
p |
표현값을 출력 |
|
run |
r |
현재 프로그램을 처음부터 실행 |
set |
|
변수 값을 변경 |
step |
s |
프로그램 다음 소스코드가 나올 때까지 실행, 함수 안으로 진입 |
where |
w |
스택 추적 출력 |
gdb로 디버깅할 프로그램 컴파일 방법
- 소스코드 컴파일이 성공적이어야한다. 프로그램 소스코드를 문제없이 컴파일했다면, 컴파일러 옵션 -g를 주어 다시 한 번 컴파일한다.
g++ -g source_code_file.cpp
참고 : -O 옵션( 최적화 )은 디버깅 할 때 빼는 것이 좋다. 왜냐하면 코드를 바꿔버리기 때문이다.
[실행하는 방법]
gdb 컴파일후 완성된 파일명
<사용 예>
gdb a.out
수행중인 프로세스를 디버깅 할 수 있다. 명령어는 다음과 같다.
gdb [프로그램명] [현재 수행중인 프로세스의 PID]
gdb -p [현재 수행중인 프로세스의 PID]
--------------------------------------------------------------------------------
자 여기까지 하면 이제 gdb를 실행 시키는 것 까지는 되었을 것이다.
다음은 gdb 사용법이다.
화면에 아래와 같이 뜰 것이다. gdb가 실행 되었다는 뜻이다.
(gdb)
l ( list ) 를 입력하면 소스 내용이 출력된다.
특정 행 보기
l [행 번호]
<사용 예>
l 10
특정 함수 보기
l [함수명]
<사용 예>
l hello
분산된 여러파일의 소스
l [파일명]:[함수명]
<사용 예>
l file.c:func
출력되는 행의 수 변경 명령어
set listsize 20 : 20 행으로 설정
프로그램을 실행하는 명령어 r ( run )
bt ( back trace ) : 스택을 백트레이스
브레이크 포인트 걸기
<사용 예>
b main
참고 : r을 하면 브레이크 포인트에서 멈춘다.
브레이크 포인트 명령
b func : func 함수의 시작 부분에 브레이크 포인트 설정
b 10 : 10행에 브레이크 포인트 설정
b fila.c:func : file.c 파일의 func 함수에 브레이크 포인트 설정
b +2 : 현재 행에서 2개행 이후 지점에 브레이크 포인트 설정
b -2 : 현재 행에서 2개행 이전 지점에 브레이크 포인트 설정
b 0x803020 : 0x803020 주소에 브레이크 포인트 설정 ( 어셈블리로 디버깅시 시용 )
b 10 if var == 0 : 10행에 브레이크 포인트 설정 ( var 변수 값이 0 일 경우에만 작동 )
condition [N] var == 0 : N번 브레이크 포인트에 var 변수가 0 일 때 동작하라고 설정
b 명령어는 gdb가 종료될 때까지 유효
한번만 브레이크 걸고 싶을 땐 +b 명령을 사용한다.
clear : 약자 cl ( 브레이크 포인트 지움 )
d : 모든 브레이크 포인트 지움
참고 : 이미 실행 중인 프로세스를 gdb 할 때 r은 재시작 k는 종료!!
이제 정밀하게 보는 명령어를 보자.
s ( step ) : 현재 행을 수행하고 멈춤, 만약 함수 호출이면 내부로 들어감
n ( next ) : 현재 행을 수행하고 멈춤, 만약 함수 호출이면 내부로 안들어가고 넘어감
c ( continue ) : 브레이크 포인트를 만날 때까지 수행
참고 : s 나 n 뒤에 숫자를 넣으면 그 숫자만큼 누른 것과 동일하다.
u ( until ) : 현재 루프를 빠져 나감 ( for문의 경우 계속 n만 누를 수 없으므로 있는 명령어다 )
finish : 현재 함수를 수행하고 빠져나감
return : 현재 함수를 수행하지 않고 빠져나감
return 123 : 현재 함수를 수행하지 않고 빠져나감 ( 리턴 값은 123 )
si : 현재 인스트럭션을 수행, 함수 호출시 내부로 들어감
ni : 현재 인스트럭션을 수행, 함수 호출시 내부로 안들어감
watch [변수명] : 변수 값이 어떻게 바뀌는지, 어떤 코드가 바꾸는지 확인할 때 편리
p [변수명] : 해당 변수값이 보임
p [함수명] : 해당 주소값이 보임
포인터 변수의 경우
p pt : 주소값
p *pt : 값
레지스트리 값 보기
p $[레지스트명]
배열을 알리는 방법 : @
p *pt@4 : 4 크기의 배열이라고 gdb에게 알려줌
출력 형식 ( 기본 defalut 10진수 )
p /[출력형식] [변수]
t : 2진수
o : 8진수
d : 부호 있는 10진수
u : 부호 없는 10진수
x : 16진수
c : 최초 1바이트값을 문자형으로 출력
f : 부동 소수점 값 형식으로 출력
a : 가장 가까운 심볼의 오프셋을 출력
display [변수명] : 변수값을 매번 화면에 디스플레이 한다.
display [출력형식] [변수명] : 변수값을 출력 형식으로 디스플레이한다.
undisplay : 디스플레이 설정을 없앤다.
disable display [디스플레이 번호] : 디스플레이를 일시 중단한다.
enable display [디스플레이 번호] : 디스플레이를 다시 활성화한다.
'장인으로의 여정' 카테고리의 다른 글
[linux] jdk 설치 (0) | 2016.03.12 |
---|---|
[linux] cut (0) | 2016.02.22 |
[linux] awk (0) | 2016.01.27 |
댓글