C++ app을 stack trace 하려면 어떻게 해야 되나요?

조회수 5698회

제가 c++ app을 만들었는데 이게 자꾸 혼자서 죽어요. stacktrace 해서 어떻게 되고 있는 건지 보고 싶은데 말만 들었지 방법을 모르겠네요

제 app은 linux/window/mac 쓰고 있고 전부 gcc로 컴파일했습니다.

app이 죽은 다음 유저가 app을 켰을 때 유저한테 물어보고 stack trace를 받아오고 싶은데요

정보를 받아오는 건 짤 수 있는데 어떤 식으로 trace정보를 저장해야 할지 모르겠습니다. 도와주세요

1 답변

  • 좋아요

    0

    싫어요
    채택 취소하기

    linux/OSX 에서 glibc, gcc컴파일러를 쓰고 있는 경우에는 execinfo.h헤더의 backtrace() 함수를 쓸 수 있습니다. backtrace()segmentation fault가 발생했을 때 stacktrace 출력해주고 exit합니다.

    관련 된 문서는 libc manual을 참고해주세요

    SIGSEGV 핸들러를 설정하고, segfault 발생 시 stacktrace를 stderr에 출력해 주는 코드를 첨부하겠습니다. *baz() 함수에서 segfault가 발생하고 handler를 불러옵니다

    #include <stdio.h>
    #include <execinfo.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <unistd.h>
    
    
    void handler(int sig) {
      void *array[10];
      size_t size;
    
      // 스택에 있는 모든 void* entry를 가져옴
      size = backtrace(array, 10);
    
      // stderr에 모든 프레임을 출력
      fprintf(stderr, "Error: signal %d:\n", sig);
      backtrace_symbols_fd(array, size, STDERR_FILENO);
      exit(1);
    }
    
    void baz() {
     int *foo = (int*)-1; // 일부러 이상한 포인터를 만들고
      printf("%d\n", *foo); // segfault를 발생
    }
    
    void bar() { baz(); }
    void foo() { bar(); }
    
    int main(int argc, char **argv) {
      signal(SIGSEGV, handler);   // 시그널 핸들러 설정
      foo(); // segfault 발생!
    }
    

    gcc 옵션 -g -rdynamicstacktracesymbol을 출력해 줍니다. 좀 더 보기 편해져요

    $ gcc -g -rdynamic ./test.c -o test 로 컴파일했을 때 결과는 다음과 같습니다

    `$ ./test
    Error: signal 11:
    ./test(handler+0x19)[0x400911]
    /lib64/tls/libc.so.6[0x3a9b92e380]
    ./test(baz+0x14)[0x400962]
    ./test(bar+0xe)[0x400983]
    ./test(foo+0xe)[0x400993]
    ./test(main+0x28)[0x4009bd]
    /lib64/tls/libc.so.6(__libc_start_main+0xdb)[0x3a9b91c4bb]
    ./test[0x40086a]
    

    모듈, offset, 함수를 확인할 수 있고 스택 top에 signal handler가, 그 밑으로 가면서 다른 함수들이 뜨는 게 보이시나요?

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)