-1

compile

# g++ -rdynamic ./test_stacktrace.cpp -o test_stacktrace
./test_stacktrace.cpp: In function ‘int main(int, char**)’:
./test_stacktrace.cpp:63:25: error: invalid use of non-static member function
  signal(SIGSEGV, b.trace);

code

/*
 *  g++ -rdynamic ./test_stacktrace.cpp -o test_stacktrace
*/

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

class Backtrace {
    public:
        Backtrace();
        void trace(int sig);
};

Backtrace::Backtrace(){}

void Backtrace::trace(int sig){
    void *trace[10];
    char **messages = (char **)NULL;
    int i, trace_size = 0;
    
    trace_size = backtrace(trace, 10);
    messages = backtrace_symbols(trace, trace_size);
    
    fprintf(stderr, "Error: signal %d:\n", sig);
    for(i=1; i<trace_size; ++i){
        fprintf(stderr, "#%d %s\n", i, messages[i]);
    }
    
    exit(1);
}

void baz(){
    int *foo = (int*)-1;
    printf("%d\n", *foo);
}

void bar() { baz(); }
void foo() { bar(); }


int main(int argc, char **argv){
    Backtrace b;
    
    signal(SIGSEGV, b.trace);
    foo();
}
Community
  • 1
  • 1
clarkk
  • 27,151
  • 72
  • 200
  • 340

2 Answers2

4

You cant add a member function, there is no way for the signal function to bind your object b. The function pointer must follow the format:

typedef void (*sighandler_t)(int);

Yours is of type::

void (Backtrace::*)(int);

You will need a either:

  1. A global function and a global instance of the class Backtrace to add as a signal handler.
  2. A static member function and static instance of the class Backtrace.

Similar examples can be found here.

However, it doesn't look like your example actually requires a class. You have no member variables. You can use trace as a free function to achieve what you want.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
0

If you define a global instance of Backtrace, you can use it in a plain function, or a lambda expression coercible to the proper type:

Backtrace b;

void bTrace(int s) { b.trace(s); }

int main() {
    signal(SIGSEGV, &bTrace);
    signal(SIGKILL, [](int s){ b.trace(s); });
}
bipll
  • 11,747
  • 1
  • 18
  • 32
  • `Backtrace b; void bTrace(int sig){ b.trace(int sig); } int main(int argc, char **argv){ signal(SIGSEGV, &bTrace); foo(); }` – clarkk Jun 21 '18 at 14:43
  • returns this error `./test_stacktrace.cpp: In function ‘void bTrace(int)’: ./test_stacktrace.cpp:38:10: error: expected primary-expression before ‘int’ b.trace(int sig); ` – clarkk Jun 21 '18 at 14:44
  • Yes, I've named the argument in lambda but forgot to in global function. See my edited post. – bipll Jun 21 '18 at 14:50