core dump file이 발생하였을 경우 이것을 가지고 디버깅 하는 방법을 소개하고자 한다.
간단한 소스 코드를 보자.
#include <stdio.h>
int main(int argc, char* argv[]) {
char buffer[16];
buffer[80000] = 3;
return;
}
gcc -g -o main main.c
ps: -g 옵션은 디버그 정보를 넣어서 컴파일을 해 주는데, 이게 없으면 core 파일을 분석 할 수 없다.
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault
core dump file이 생성되지 않을 경우는 막아 놓았기 때문인데, ulimit 를 사용해서
이것을 풀어줄 수 있다.
ulimit -c 1024 (core file 용량을 정해준다.)
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault (core dumped)
frank@tightrope:~/tmp/gdbtest$ ls -als core
72 -rw------- 1 frank frank 147456 2006-01-13 21:19 core
분석을 해 보도록 하겠다.
frank@tightrope:~/tmp/gdbtest$ gdb ./main ./core
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".
Core was generated by `./main'.
Program terminated with signal 11, Segmentation fault.
warning: current_sos: Can't read pathname for load map: Input/output error
Reading symbols from /lib/tls/i686/cmov/libc.so.6...done.
Loaded symbols for /lib/tls/i686/cmov/libc.so.6
Reading symbols from /lib/ld-linux.so.2...done.
Loaded symbols for /lib/ld-linux.so.2
#0 main (argc=1, argv=0xbfca9944) at main.c:6
6 buffer[80000] = 3;
(gdb)
이걸 보고 우리는 main 함수에서 Segmentation fault로 종료되었다는 것을 알 수 있다.
함수 이름과 매개변수 값, 몇 번째 줄에서 segmentation fault가 났는지 보여준다.
이제는 조금 더 복잡한 소스를 디버깅해 보도록 해 보자.
#include <stdio.h>
int main(int argc, char* argv[]) {
// notice the erroneous "=", the coder meant "=="
if(argv = 0) return;
printString(argv);
return;
}
컴파일 하고 실행해 보자.
frank@tightrope:~/tmp/gdbtest$ gcc -g -o main main.c
frank@tightrope:~/tmp/gdbtest$ ./main
Segmentation fault (core dumped)
frank@tightrope:~/tmp/gdbtest$ ls -als core
68 -rw------- 1 frank frank 147456 2006-01-13 21:53 core
이제 디버깅을 해 보도록 하자.
frank@tightrope:~/tmp/gdbtest$ gdb ./main ./core
GNU gdb 6.3-debian
Copyright 2004 Free Software Foundation, Inc.
...
#0 0x08048396 in printString (string=0x0) at main.c:14
14 sprintf(string, "This is a test.\n");
#0 줄을 보면 string 이 널 포인터라는게 분명하다. 그런데 우리는 이게 어디서 왔는지
모른다. 단서는 파일 main.c에 14번 째 줄이라는 것과 main 에서 에러가 발생하지
않았다는 것이다. 그래서 우리는 backtrace를 할 것이다.
(gdb) backtrace
#0 0x08048396 in printString (string=0x0) at main.c:14
#1 0x0804837c in main (argc=1, argv=0x0) at main.c:8
'backtrace' 명령어는 함수를 연대기순으로 나열해 준다. 맨 위에 줄이 segmentation fault
가 발생한 소스이다. 저걸 보면 main.c:8 에서 main.c:14를 호출한 것을 알 수 있다.
더 많은 정보를 얻기 위해 'frame' 명령을 사용하도록 하자. 'frame' 명령은 'backtrace'
명령 실행으로 나온 항목들에 대해 더 많은 정보를 보여준다.
(gdb) frame 0
#0 0x08048396 in printString (string=0x0) at main.c:14
14 sprintf(string, "This is a test.\n");
(gdb) frame 1
#1 0x0804837c in main (argc=1, argv=0x0) at main.c:8
8 printString(argv);
이것을 보면 이미 main.c:8 에서 argv가 0으로 값이 넘어간 것을 알 수 있다.
*잡다한 tip
스레드를 사용해서 프로그래밍을 할 때 threadsafe 함수를 사용해야 한다. 예를 들어서 localtime
함수는 언젠가 프로그램과 충동할 것이다. 그 대신에 localtime_r 함수를 쓰는게 좋다. localtime_r
함수는 threadsafe 함수이다.
'Computer_language > Comfile' 카테고리의 다른 글
[Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) [출처] [Tip] win32k.sys 덤프가 뜰 경우..(메모리 테스트 프로그램들) (0) | 2009.01.12 |
---|---|
프로그램 덤프 뜨기... (0) | 2009.01.12 |
NS2 - 무선환경 시뮬레이션 (0) | 2009.01.12 |
[EJB] 객체지향과 컴포넌트 프로그래밍 [출처] [EJB] 객체지향과 컴포넌트 프로그래밍|작성자 젠센쭈 (0) | 2009.01.12 |