gdb로 디버깅

GNU 디버거(gdb)를 사용하면 프로그램이 실행되는 동안 다른 프로그램의 내부를 조사하고 충돌 발생 시점에 프로그램이 수행 중이던 작업을 살펴볼 수 있습니다.

gdb를 통해 코드 실행을 조사 및 제어할 수 있으며 충돌의 원인 또는 일반적으로 잘못된 동작의 원인을 평가하는 데 유용합니다. gdb 는 Java™ 프로세스를 처리하지 않으므로 순수 Java 프로그램에서는 사용이 제한됩니다. 원시 라이브러리 및 JVM 자체를 디버깅하는 데 유용합니다.

gdb 실행

다음과 같은 세 가지 방법으로 gdb를 실행할 수 있습니다.

프로그램 시작
일반적으로 gdb <application> 명령은 gdb 제어 하에 프로그램을 시작하는 데 사용됩니다. 그러나 Java가 실행되는 방법 때문에 환경 변수를 설정한 후 Java를 호출하여 gdb 를 시작해야 합니다.
export IBM_JVM_DEBUG_PROG=gdb
java
그런 다음 gdb 프롬프트를 수신하고 실행 명령 및 Java 인수를 제공합니다.
r <java_arguments>
실행 중인 프로그램에 접속
Java 프로그램이 이미 실행 중인 경우 gdb에서 제어할 수 있습니다. 실행 중인 프로그램의 프로세스 ID가 필요한 경우 gdb 는 첫 번째 인수로 Java 애플리케이션을 사용하고 두 번째 인수로 프로세스 ID를 사용하여 시작됩니다.
gdb <Java Executable> <PID>

gdb가 실행 중인 프로그램에 연결되면 이 프로그램이 정지되고 코드의 해당 부분이 뷰어에 표시됩니다. 그렇게 되면 프로그램이 gdb의 제어를 받게 되고 사용자는 명령을 발행하기 시작하여 변수를 설정 및 표시하고 일반적으로 코드의 실행을 제어할 수 있게 됩니다.

시스템 덤프에서 실행(corefile)
시스템 덤프는 일반적으로 프로그램 충돌이 발생하는 경우 생성됩니다. gdb는 이 시스템 덤프에서 실행할 수 있습니다. 시스템 덤프에는 충돌이 발생한 때의 프로그램 상태가 포함되어 있습니다. gdb를 사용하면 충돌을 발생시킨 레지스터 및 모든 변수 값을 조사합니다. 이 정보는 충돌의 원인을 파악하는 데 도움이 됩니다. 시스템 덤프를 디버그하려면 첫 번째 인수로 Java 애플리케이션 파일을 사용하고 두 번째 인수로 시스템 덤프 이름을 사용하여 gdb 를 시작하십시오.
gdb <Java Executable> <system dump>

시스템 덤프에 대해 gdb를 실행하면 초기에 프로그램에서 수신한 종료 신호, 이때 실행된 함수 및 결함을 생성한 코드의 행과 같은 정보를 보여줍니다.

프로그램이 gdb의 제어 하에 놓이면 시작 메시지가 표시되고 그 뒤에 프롬프트 (gdb) 가 표시됩니다. 프로그램이 사용자가 지시사항을 입력하기를 기다리는 중입니다. 각 명령어에 대해 프로그램은 계속해서 사용자의 선택을 안내합니다.

중단점 및 감시점 설정

다음 명령을 사용하여 특정 행 또는 함수에 대해 중단점을 설정할 수 있습니다.

break linenumber

또는

break functionName

중단점을 설정하고 나면 continue 명령을 사용하여 프로그램이 중단점에 도달할 때까지 실행되도록 하십시오.

지정된 조건에 도달할 경우에만 프로그램이 정지되도록 조건을 사용하여 중단점을 설정하십시오. 예를 들어, breakpoint 39 if var == value를 사용하면 변수가 지정된 값과 동일한 경우에 한해 프로그램이 39행에 도달하면 정지됩니다.

변수가 특정 값이 되는 위치시점을 알아보기 위해 감시점을 사용할 수 있습니다. 해당 변수가 범위 내에 있는 경우 감시점을 설정하십시오. 이를 수행하고 나면 이 변수가 특정 값이 될 때마다 경보가 표시됩니다. 명령 구문은 watch var == value입니다.

어떤 중단점 및 감시점이 설정되었는지 확인하려면 info 명령을 사용하십시오.

info break
info watch
gdb가 중단점 또는 감시점에 도달하면 다음으로 실행하게 설정된 코드의 행을 인쇄합니다. 8행에서 중단점을 설정하면 행 7의 실행을 완료한 후 8행을 실행하기 전에 프로그램이 정지됩니다. 중단점 및 감시점 뿐만 아니라 특정 시스템 신호를 수신할 때 프로그램도 정지합니다. 다음 명령을 사용하면 이러한 시스템 신호를 수신할 때마다 정지되는 디버깅 도구를 중지할 수 있습니다.
handle sig32 pass nostop noprint 
handle sigusr2 pass nostop noprint 

코드 조사

코드의 올바른 위치에 도달하면 코드를 조사할 수 있는 다양한 방법이 있습니다. 가장 유용한 것은 호출 스택을 표시하는 backtrace(bt(으)로 축약됨)입니다. 호출 스택은 각 함수 프레임에는 함수 매개변수 및 로컬 변수 등의 정보가 포함되어 있는 함수 프레임의 콜렉션입니다. 이러한 함수 프레임은 실행되는 순서대로 호출 스택에 배치됩니다. 즉, 가장 최근에 호출된 함수가 호출 스택의 맨 위에 표시됩니다. 호출 스택을 조사하면 프로그램의 실행을 추적할 수 있습니다. 호출 스택이 표시되는 경우 행의 시작 부분에 프레임 번호가 표시되고, 이어서 호출 함수의 주소, 다음으로는 함수 이름과 함수에 대한 소스 파일이 표시됩니다. 예를 들어,
#6 0x804c4d8 in myFunction () at myApplication.c

함수 프레임에 대한 자세한 정보를 보려면 프레임 번호를 지정하는 매개변수와 함께 frame 명령을 사용하십시오. 프레임을 선택한 후 print var 명령을 사용하여 변수를 표시할 수 있습니다.

print 명령을 사용하여 변수 값을 변경하십시오(예: print var = newValue).

info locals 명령은 선택된 함수에 있는 모든 로컬 변수의 값을 표시합니다.

프로그램 실행의 정확한 시퀀스를 수행하려면 stepnext 명령을 사용하십시오. 두 명령 모두 실행할 행 번호를 지정하는 선택적 매개변수를 사용합니다. 그러나 next은(는) 함수 호출을 단일 실행 행으로 처리하는 반면, step은(는) 호출된 함수의 각 행을 한 번에 한 단계씩 진행합니다.

유용한 명령

코드 디버깅을 완료하면 run 명령으로 프로그램이 종료 또는 크래시 지점까지 실행됩니다. quit 명령은 gdb를 종료하는 데 사용됩니다.

기타 유용한 명령은 다음과 같습니다.

ptype
변수의 데이터 유형을 인쇄합니다.
info share
현재 로드되는 공유 라이브러리의 이름을 인쇄합니다.
info functions
모든 함수 프로토타입을 인쇄합니다.
list
현재 행 주위의 소스 코드 10줄을 표시합니다.
help
호출된 help 명령을 포함할 수 있는 주제 목록을 표시하여 해당 주제에 대한 세부 도움말을 표시합니다.