[C언어] backtrace 방법

backtrace는 프로그램의 실행 중 호출된 함수들의 스택을 추적하여 오류나 크래시 발생 시 해당 문제가 발생한 위치와 그 경로를 파악하는 데 유용한 도구이다 .주로 디버깅 시 사용되며, 특히 프로그램이 비정상 종료되었을 때 그 원인을 추적하는 데 도움을 준다. 이 글에서는 C/C++ 프로그램에서 backtrace 사용 방법에 대해 알아본다.

GNU backtrace() 함수 사용

GNU C 라이브러리는 backtrace()backtrace_symbols() 함수를 제공하여 백트레이스를 쉽게 생성할 수 있다. 이 함수들은 표준 라이브러리에 포함되어 있어 별도의 설치가 필요하지 않고 사용할 수 있다.

예제 코드

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

void print_backtrace() {
    void *array[10];
    size_t size;
    char **strings;
    size_t i;

    // 백트레이스 생성
    size = backtrace(array, 10);

    // 백트레이스의 심볼을 변환
    strings = backtrace_symbols(array, size);

    printf("Obtained %zu stack frames.\n", size);

    for (i = 0; i < size; i++) {
        printf("%s\n", strings[i]);
    }

    free(strings);
}

void function2() {
    print_backtrace();
}

void function1() {
    function2();
}

int main(int argc, char *argv[]) {
    function1();
    return 0;
}

컴파일 및 실행

gcc -o backtrace_example backtrace_example.c -rdynamic
./backtrace_example
Obtained 6 stack frames.
./backtrace_example(print_backtrace+0x2c) [0x55fc0681b215]
./backtrace_example(function2+0x12) [0x55fc0681b2b7]
./backtrace_example(function1+0x12) [0x55fc0681b2cc]
./backtrace_example(main+0x1d) [0x55fc0681b2ec]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3) [0x7f9077e77083]
./backtrace_example(_start+0x2e) [0x55fc0681b12e]

gdb를 사용한 백트레이스

gdb(GNU Debugger)는 C/C++ 프로그램의 디버깅을 위한 강력한 도구로, 실행 중 또는 프로그램이 크래시한 이후에 백트레이스를 생성할 수 있다.

다음은 gdb를 사용하여 백트레이스를 확인하는 방법이다.

1. 프로그램에 디버그 심볼을 포함하여 컴파일

    gcc -g -o my_program my_program.c

    2. gdb로 프로그램 실행

    gdb ./my_program

      3. gdb 내에서 프로그램을 실행

      (gdb) run

      4. 프로그램이 원하는 위치에서 중단된 상태에서 backtrace 실행

      (gdb) backtrace

      출력 예시

      #0  0x00007ffff7a4d527 in __GI_raise (sig=sig@entry=0x6) at ../sysdeps/unix/sysv/linux/raise.c:51
      #1  0x00007ffff7a4e9aa in __GI_abort () at abort.c:89
      #2  0x0000555555554719 in function2 () at my_program.c:15
      #3  0x0000555555554739 in function1 () at my_program.c:19
      #4  0x0000555555554749 in main (argc=1, argv=0x7fffffffe2b8) at my_program.c:23

      SIGSEGV와 같은 시그널 처리 시 백트레이스 생성

      프로그램이 SIGSEGV와 같은 시그널에 의해 크래쉬가 발생 했을 때 자동으로 백트레이스를 생성하면 디버깅 하는데 도움이 된다.

      예제

      #include <execinfo.h>
      #include <signal.h>
      #include <stdio.h>
      #include <stdlib.h>
      #include <unistd.h>
      
      void handle_sigsegv(int sig) {
          void *array[10];
          size_t size;
      
          // 백트레이스 생성
          size = backtrace(array, 10);
      
          // 백트레이스 출력
          fprintf(stderr, "Error: signal %d:\n", sig);
          backtrace_symbols_fd(array, size, STDERR_FILENO);
          exit(1);
      }
      
      int main() {
          signal(SIGSEGV, handle_sigsegv);
      
          // 잘못된 메모리 참조 (Segmentation Fault 유도)
          int *p = NULL;
          *p = 0;
      
          return 0;
      }

      컴파일 및 실행

      gcc -o sigsegv_example sigsegv_example.c -rdynamic
      ./sigsegv_example
      Error: signal 11:
      ./sigsegv_example(handle_sigsegv+0x2f)[0x55e1625e71f8]
      /lib/x86_64-linux-gnu/libc.so.6(+0x43090)[0x7fadb6017090]
      ./sigsegv_example(main+0x29)[0x55e1625e7268]
      /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0x7fadb5ff8083]
      ./sigsegv_example(_start+0x2e)[0x55e1625e710e]

      참고 사이트

      답글 남기기