#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#define BACKTRACE_BUFFER_SIZE 256
void func_2(void)
{
int i, nptrs;
void *buffer[BACKTRACE_BUFFER_SIZE];
char **strings = NULL;
nptrs = backtrace(buffer, BACKTRACE_BUFFER_SIZE);
strings = backtrace_symbols(buffer, nptrs);
if (!strings) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (i = 0; i < nptrs; i++) {
printf("%s\n", strings[i]);
}
free(strings);
}
void func_1(void)
{
func_2();
}
int main(void)
{
func_1();
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#define BACKTRACE_BUFFER_SIZE 256
void func_2(void)
{
int i, nptrs;
void *buffer[BACKTRACE_BUFFER_SIZE];
char **strings = NULL;
nptrs = backtrace(buffer, BACKTRACE_BUFFER_SIZE);
strings = backtrace_symbols(buffer, nptrs);
if (!strings) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (i = 0; i < nptrs; i++) {
printf("%s\n", strings[i]);
}
free(strings);
}
void func_1(void)
{
func_2();
}
int main(void)
{
func_1();
return 0;
}
아래는 예제 코드를 컴파일하고 실행한 결과이다. 참고로 -O2 등의 최적화가 들어가면 콜스택이 변할 수 있다. 불필요한 함수 호출을 컴파일러가 제거하기 때문이다.
superkkt@~/tmp$ gcc -Wall -g -rdynamic -o backtrace backtrace.c
superkkt@~/tmp$ ./backtrace
./backtrace(func_2+0x27) [0x4008db]
./backtrace(func_1+0x9) [0x400955]
./backtrace(main+0x9) [0x400960]
/lib/libc.so.6(__libc_start_main+0xfe) [0x7f7fcbaacd8e]
./backtrace() [0x4007f9]
superkkt@~/tmp$ ./backtrace
./backtrace(func_2+0x27) [0x4008db]
./backtrace(func_1+0x9) [0x400955]
./backtrace(main+0x9) [0x400960]
/lib/libc.so.6(__libc_start_main+0xfe) [0x7f7fcbaacd8e]
./backtrace() [0x4007f9]
Segmentation Fault 상황에서 시그널 핸들러를 사용해서 로그를 남기는 방법은 참조된 사이트를 참고한다.
<References>
Stack Backtracing Inside Your Program

comments
comments rss (+댓글 쓰러가기)