gdb, 프로그램이 어디서 죽었는지 보는 법
gdb는 GNU 디버거로, 프로그램을 멈춰 가며 어디서 죽었는지와 변수 값을 봅니다.
이 글은 GNU GDB 공식 매뉴얼(Debugging with GDB, Tenth Edition, current onlinedocs)을 2026-09-01 기준으로 정리한 일반 설명이며, 대상과 빌드 옵션에 따라 세부 동작은 달라질 수 있습니다.
gdb는 무엇인가?
한 줄 답: 이 디버거는 프로그램이 실행되는 동안, 또는 죽은 순간에 안에서 무엇이 일어났는지 보게 하는 GNU 소스 수준 디버거입니다.
공식 매뉴얼은 이 도구를 다른 프로그램이 실행되는 동안 내부에서 무슨 일이 일어나는지, 또는 프로그램이 크래시한 순간 무엇을 하고 있었는지 확인하게 하는 소스 수준 디버거로 설명합니다. 프로그램을 시작하고, 지정한 조건에서 멈추고, 멈춘 뒤 상태를 살피며, 상태를 바꿔 다른 결과를 실험하는 네 가지 일을 지원합니다. 이 글에서는 그중 시작·중단·상태 확인으로 크래시 위치를 좁히는 흐름만 다룹니다. C와 C++로 작성한 프로그램을 디버깅할 수 있으며, 컴파일 시스템이나 메모리 오류 검사기가 아니라 실행 중인 프로그램의 위치와 상태를 확인하는 도구입니다.
어떻게 시작하나?
한 줄 답: 실행 파일명을 인자로 gdb를 연 뒤, 효과적인 디버깅을 위해 -g로 컴파일한 프로그램을 run으로 시작합니다.
효과적인 디버깅을 위해서는 컴파일할 때 -g를 지정해야 합니다. 이 정보는 오브젝트 파일에 저장되어 변수와 함수의 자료형, 소스 줄 번호와 실행 주소의 대응을 설명합니다. GCC는 -g를 -O와 함께 지원하지만, 최적화가 적용되면 일부 값의 확인이 제한될 수 있습니다.
가장 일반적인 실행 파일 지정과 인수 전달은 다음과 같이 시작합니다.
gdb program
gdb --args gcc -O2 -c foo.c
첫 번째 형식은 실행 파일을 열고, 두 번째 형식은 gcc를 대상 프로그램으로 열면서 -O2 -c foo.c를 그 프로그램의 인수로 넘깁니다. run 또는 r은 지정된 프로그램을 바로 시작합니다. start는 C와 C++의 main 시작점에 임시 breakpoint를 설정한 뒤 실행하는 흐름입니다. 정적·전역 객체 생성자는 main보다 먼저 실행될 수 있으므로 C++에서는 main에 도달하기 전에 멈출 수 있지만 임시 breakpoint는 남아 있습니다.
종료는 quit 또는 q로 하며, 실행 파일과 core 파일을 함께 열거나 실행 중인 PID에 연결하는 방식도 지원하지만 여기서는 절차를 확장하지 않습니다.
breakpoint와 run은 어떻게 쓰나?
한 줄 답: break로 함수·줄·주소에 멈춤 지점을 만든 뒤 run으로 실행하면, 해당 명령 직전에 프로그램이 멈춥니다.
멈출 위치는 break 또는 약칭 b 뒤의 locspec으로 지정합니다. locspec은 함수 이름, 줄 번호, 명령어 주소 등으로 해석됩니다. 하나의 breakpoint가 인라인 함수·C++ 템플릿·오버로드 이름에 대응하는 여러 코드 위치로 풀릴 수 있다는 점도 알아둘 필요가 있습니다. 지정 위치의 명령을 실행하기 직전에 중단하므로, 즉시 시작하는 run보다 먼저 관찰 지점을 설정해야 합니다.
(gdb) b main
(gdb) run
이 순서에서는 main에 먼저 중단 지점을 만든 뒤 실행하므로 프로그램이 관찰 지점을 지나쳐 버리는 것을 막습니다. 조건을 붙인 break … if cond는 조건식이 참일 때만 멈춥니다. tbreak는 한 번 멈춘 뒤 자동으로 삭제되는 임시 breakpoint이며, info break는 설정되어 있는 목록을 보여 줍니다.
backtrace와 print는 무엇을 보나?
한 줄 답: backtrace는 현재 프레임부터 호출 스택을 한 줄씩 보여 주고, print는 멈춘 지점의 식·변수 값을 출력합니다.
backtrace 또는 bt는 현재 실행 프레임을 frame 0으로 삼고, 그 호출자 방향으로 스택을 한 줄씩 출력합니다. 각 프레임에서 함수 이름을 확인할 수 있으며, 보통 프레임 번호·프로그램 카운터·소스 파일·줄 번호·인수가 함께 표시됩니다. bt 3은 가장 안쪽 세 프레임만 보고, -full은 지역 변수 값까지 출력합니다.
멈춘 뒤에는 다음처럼 호출 경로와 현재 범위의 값을 차례로 확인할 수 있습니다.
(gdb) backtrace
(gdb) print variable
최적화된 코드에서는 사용하지 않는 인수나 지역 변수가 <optimized out>으로 표시될 수 있습니다. 지역 변수가 보이지 않거나 값이 부정확해 보이면 현재 선택한 스택 프레임에서 보이는 범위에 있는지 확인하고, 정확한 값을 확인해야 할 때는 최적화를 끄고 다시 컴파일합니다. print 또는 p는 소스 언어의 식을 평가해 출력하며, 변수 이름은 선택한 프레임의 범위에서 해석됩니다. 식을 생략하면 마지막으로 출력한 값을 다시 표시합니다.
FAQ
한 줄 답: 디버그 정보를 준비하고 멈춤 지점을 만든 뒤 스택과 현재 프레임의 값을 보면 크래시 위치를 좁힐 수 있습니다.
| 질문 | 답변 |
|---|---|
| 디버그 정보 없이 실행 파일만 열어도 됩니까? | 실행 자체는 가능할 수 있지만 효과적인 확인에는 -g가 필요합니다. 디버그 정보가 없으면 변수·함수의 자료형과 소스 줄 번호·주소의 대응을 활용하기 어렵습니다. |
run과 start는 무엇이 다릅니까? | run은 지정한 프로그램을 바로 시작합니다. start는 main 시작점에 임시 breakpoint를 만든 뒤 실행하므로 첫 코드 근처에서 확인할 수 있습니다. C++의 정적·전역 객체 생성자는 main보다 먼저 실행될 수 있지만 임시 breakpoint는 남아 있습니다. |
| 최적화된 바이너리에서도 스택을 볼 수 있습니까? | 스택 프레임은 볼 수 있습니다. 다만 사용하지 않는 인수나 지역 값이 <optimized out>으로 나올 수 있으므로, 정확한 지역 값을 확인하려면 최적화를 끄고 다시 컴파일하는 편이 낫습니다. |
원격 대상에서 run이 거부되면 어떻게 합니까? | 일부 remote 대상은 run을 지원하지 않으므로 continue를 사용해야 합니다. 필요한 경우 먼저 load가 필요할 수 있습니다. |
출처
한 줄 답: 본문 사실과 명령은 2026-09-01 기준으로 확인한 sourceware.org의 GNU GDB 공식 문서만 사용합니다.
- Debugging with GDB — 디버거의 목적, 주요 기능, C·C++ 지원 범위를 확인했습니다.
- Invoking GDB — 실행 파일 지정,
--args, core 파일·PID 연결 방식을 확인했습니다. - Compilation —
-g디버그 정보와-O최적화의 관계를 확인했습니다. - Starting your Program —
run,start, 원격 대상에서의 시작 제약을 확인했습니다. - Setting Breakpoints —
break, locspec, 조건부·임시 breakpoint, 목록 확인을 확인했습니다. - Backtraces — 프레임 순서,
bt의 개수 지정과-full, 최적화에 따른 표시를 확인했습니다. - Examining Data —
print의 식 평가와 마지막 값 재표시를 확인했습니다. - Program Variables — 선택한 프레임의 변수 범위와 최적화에 따른 제약을 확인했습니다.
- Quitting GDB —
quit와q를 통한 종료를 확인했습니다.