segmentation fault를 gdb로 디버깅하기

jinwook han·2023년 4월 15일
0

gdb를 사용하여 segmentation fault의 원인을 파악한다.

segmentation fault

프로그램을 실행하는 중 segmentation fault가 발생했다.
segmentation fault:
https://en.wikipedia.org/wiki/Segmentation_fault

gdb

gdb를 사용한다.
gdb: gdb는 c와 c++ 프로그램을 디버깅할 수 있는 툴이다.
https://sourceware.org/gdb/current/onlinedocs/gdb.html/Summary.html#Summary

gcc

gdb로 디버깅하는게 가능하도록 컴파일한다.

gcc -Wall -g -o head head.c

-Wall:
warning을 더 많이 보여준다.(추측이지만 warning+all인 것 같다)
https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html

-g:
디버깅 정보를 생성한다. gdb에서 생성한 정보를 사용한다.
https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options

-o:
출력 파일 이름을 설정할 수 있다.

gdb

  1. gdb를 실행한다.
gdb ./test

sudo 권한이 필요하면 sudo gdb ./test를 실행한다.

  1. run 매개변수를 실행한다.
    매개변수에는 디버깅 대상 프로그램에 넣었던 매개변수를 그대로 넣는다.
    예로 들어 ./test localhost 80 으로 프로그램을 실행한다면, run localhost 80을 실행한다.

    프로그램이 실행되는 것을 볼 수 있다.

    어떤 쓰레드에서 segmentation fault가 발생하는지 알려준다.
    여기서 자세한 segmentation fault를 보고 싶으면 backtrace를 실행한다.

  2. backtrace를 실행한다.

    #5를 보면 프로그램의 116번 줄 코드에서 segment fault가 났다는 것을 알 수 있다.
    frame을 실행해서 116번 코드의 내용을 보자.

  3. frame 5를 실행한다.
    backtrace에서 5번째 스택에 담긴 frame의 내용을 보고 싶다.

    address를 출력하는 부분에서 segmentation fault가 발생했다.
    segmentation fault가 어디서 발생했는지에 대한 추적이 끝났다.

addr = inet_ntop(AF_INET, &sinp->sin_addr, abuf, INET_ADDRSTRLEN);
printf("address: %s\n", addr? addr: "unknown");

코드에서 보면 addr는 inet_ntop의 리턴값이다.
inet_ntop이 잘못된 결과를 반환하는 것 같다.
프로그램을 컴파일하면 inet_ntop 관련 warning 로그가 나왔는데, 무시하고 지나쳤었다.

inet_ntop을 실행하기 위한 의존성을 추가했다.

#include <arpa/inet.h>

inet_ntop 함수는 arpa/inet.h에 정의되어 있다.
https://man7.org/linux/man-pages/man3/inet_ntop.3.html

더하며

디버깅을 하기 전, 문제가 된 116번 라인이 아니라 112번 라인에서 에러가 났다고 의심했었다.
왜냐하면, 112번 라인이 출력되지 않았기 때문이다.
알고보니 112번 라인이 flush가 되지 않아 116번에서 에러가 났음에도 불구하고 출력이 안 됐다.
모든 출력 코드에 \n을 추가하여 한 줄마다 자동으로 flush되도록 수정했다.

0개의 댓글