gdb를 사용하여 segmentation fault의 원인을 파악한다.
프로그램을 실행하는 중 segmentation fault가 발생했다.
segmentation fault:
https://en.wikipedia.org/wiki/Segmentation_fault
gdb를 사용한다.
gdb: gdb는 c와 c++ 프로그램을 디버깅할 수 있는 툴이다.
https://sourceware.org/gdb/current/onlinedocs/gdb.html/Summary.html#Summary
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 ./test
sudo 권한이 필요하면 sudo gdb ./test
를 실행한다.
run 매개변수를 실행한다.
매개변수에는 디버깅 대상 프로그램에 넣었던 매개변수를 그대로 넣는다.
예로 들어 ./test localhost 80
으로 프로그램을 실행한다면, run localhost 80
을 실행한다.
프로그램이 실행되는 것을 볼 수 있다.
어떤 쓰레드에서 segmentation fault가 발생하는지 알려준다.
여기서 자세한 segmentation fault를 보고 싶으면 backtrace를 실행한다.
backtrace
를 실행한다.
#5를 보면 프로그램의 116번 줄 코드에서 segment fault가 났다는 것을 알 수 있다.
frame을 실행해서 116번 코드의 내용을 보자.
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되도록 수정했다.