1

此代码始终无法在 ubuntu 12.04、12.10、linux mint 13 和 14 中构建,但它可以在 ubuntu maverick 10.10 上正确编译

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

//#define __USE_GNU
//#include <sys/ucontext.h>

#include <ucontext.h>
#ifndef __USE_GNU
#error "__USE_GNU HAS been undefined"
#endif
#include <cxxabi.h>
#include <iostream>


#ifndef _SYS_UCONTEXT_H
#error "sys/context HAS NOT BEEN INCLUDED"
#endif

void print_trace(const char * file, int line) //(FILE *out, const char *file, int line)
{
    const size_t max_depth = 100;
    size_t stack_depth;
    void *stack_addrs[max_depth];
    char **stack_strings;

    stack_depth = backtrace(stack_addrs, max_depth);
    stack_strings = backtrace_symbols(stack_addrs, stack_depth);

    //fprintf(out, "Call stack from %s:%d:\n", file, line);
// demangle output: http://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_demangling.html
    // spec: http://www.ib.cnea.gov.ar/~oop/biblio/libstdc++/namespaceabi.html

    //string binary;
    // Usually e.start=1: we skip the first frame (traced_exception constructor)
    for( size_t i=1; i<stack_depth; ++i ){
        char *line = stack_strings[i];
        char *lb = strchr(line, '(');
        char *plus = 0;
        char *rb = 0;
        char *demangled = 0;
        if( lb != 0 ){
            /* Print out the path to the binary? Seems pointless.
            if( binary != string( line, lb-line ) ){
                binary = string( line, lb-line );
                stream << "in " << binary << ":\n";
            }
            */
            *lb = '\0';
            plus = strchr(lb+1,'+');
            if( plus != 0 ){
                *plus = '\0';
                int status;
                demangled = abi::__cxa_demangle(lb+1, 0, 0, &status);
                /*if( status != 0 ){
                    cerr << "status: "<<status<<"\tstring:"<<lb+1<<endl;
                }*/
                rb = strchr(plus+1, ')');
            }else{
                rb = strchr(lb+1, ')');
            }
            if( rb != 0 ){
                *rb = '\0';
            }
        }
        if( lb == 0 ){
            std::cout << line;
        }else{
            if( plus != 0 ){
                std::cout << "+" << (plus+1);
            }
            if( demangled != 0 ){
                std::cout << '\t' << demangled;
                free(demangled);
            }else if( lb != 0 && rb > lb ){
                std::cout << '\t' << (lb+1) << "()";
            }
        }
        std::cout << '\n';
    }
    free(stack_strings); // malloc()ed by backtrace_symbols
}


void bt_sighandler(int sig, siginfo_t *info,
                   void *secret) {

  printf("<<< SIGNAL HANDLER >>>\n");
  print_trace("none" , 0);
  void *trace[16];
  char **messages = (char **)NULL;
  int i, trace_size = 0;
  ucontext_t *uc = (ucontext_t *)secret;

  /* Do something useful with siginfo_t */
  if (sig == SIGSEGV)
    printf("Got signal %d, faulty address is %p, "
           "from %p\n", sig, info->si_addr, 
           uc->uc_mcontext.gregs[REG_EIP]);
  else
    printf("Got signal %d#92;\n", sig);

  trace_size = backtrace(trace, 16);
  /* overwrite sigaction with caller's address */
  trace[1] = (void *) uc->uc_mcontext.gregs[REG_EIP];

  messages = backtrace_symbols(trace, trace_size);
  /* skip first stack frame (points here) */
  printf("[bt] Execution path:#92;\n");
  for (i=1; i<trace_size; ++i)
  {
    printf("[bt] %s :", messages[i]);
    char syscom[256];
    sprintf(syscom,"addr2line %p -e %s", trace[i] , "executableName" ); //last parameter is the name of this app
    system(syscom);
    printf("\n");
  }
  exit(0);
}



inline void initialise_signal_handlers()
{
    /* Install our signal handler */
    printf(" initialising signal handlers... \n ");
    struct sigaction sa;

    sa.sa_sigaction = bt_sighandler;
    sigemptyset (&sa.sa_mask);
    sa.sa_flags = SA_RESTART | SA_SIGINFO;


    sigaction(SIGSEGV, &sa, NULL);
    sigaction(SIGUSR1, &sa, NULL);
    sigaction(SIGABRT, &sa, NULL);
    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGBUS, &sa, NULL);
    sigaction(SIGSTKFLT, &sa, NULL);
    sigaction(SIGSYS, &sa, NULL);

    printf(" signal handlers initialised successfully \n ");
}

我尝试用

g++ -c SignalHandlers.cpp 
SignalHandlers.cpp: In function ‘void bt_sighandler(int, siginfo_t*, void*)’:
SignalHandlers.cpp:146:34: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp:152:45: error: ‘REG_EIP’ was not declared in this scope

显然,在 Maverick 之后,/usr/include/sys/ 被移动到/usr/include/x86_64-linux-gnu/sys,但 g++ 编译器路径在此移动之后从未更新。(这就是为什么强制更新操作系统从来都不是一个好主意,最好在更新后让尘埃落定,但似乎这一个上的尘埃兔子仍然受到旋风的影响。)

在任何情况下,直接在 ubuntu 12.04 上包含路径也不起作用:

$ g++ -I/usr/include/x86_64-linux-gnu/sys -c SignalHandlers.cpp 
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
..............................................
                 from SignalHandlers.cpp:4:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
 ..... and a lot more of those
                 from SignalHandlers.cpp:6:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/signal.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/signal.h:1,
.... and lots and lots more of those
                 from /usr/include/x86_64-linux-gnu/sys/ucontext.h:23,
                 from SignalHandlers.cpp:14:
/usr/include/x86_64-linux-gnu/sys/signal.h:1:20: error: #include nested too deeply
In file included from /usr/include/x86_64-linux-gnu/sys/unistd.h:1:0,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
                 from /usr/include/x86_64-linux-gnu/sys/unistd.h:1,
.... lots and lots of that error
                 from /usr/include/c++/4.6/x86_64-linux-gnu/./bits/gthr-default.h:42,
                 from /usr/include/c++/4.6/x86_64-linux-gnu/./bits/gthr.h:170,
                 from /usr/include/c++/4.6/ext/atomicity.h:34,
                 from /usr/include/c++/4.6/bits/ios_base.h:41,
                 from /usr/include/c++/4.6/ios:43,
                 from /usr/include/c++/4.6/ostream:40,
                 from /usr/include/c++/4.6/iostream:40,
                 from SignalHandlers.cpp:19:
/usr/include/x86_64-linux-gnu/sys/unistd.h:1:20: error: #include nested too deeply
In file included from SignalHandlers.cpp:14:0:
/usr/include/x86_64-linux-gnu/sys/ucontext.h:139:5: error: ‘stack_t’ does not name a type
SignalHandlers.cpp:132:29: error: ‘siginfo_t’ has not been declared
SignalHandlers.cpp: In function ‘void bt_sighandler(int, int*, void*)’:
SignalHandlers.cpp:143:14: error: ‘SIGSEGV’ was not declared in this scope
SignalHandlers.cpp:145:36: error: request for member ‘si_addr’ in ‘* info’, which is of non-class type ‘int’
SignalHandlers.cpp:146:34: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp:152:45: error: ‘REG_EIP’ was not declared in this scope
SignalHandlers.cpp: In function ‘void initialise_signal_handlers()’:
SignalHandlers.cpp:174:22: error: aggregate ‘initialise_signal_handlers()::sigaction sa’ has incomplete type and cannot be defined
SignalHandlers.cpp:177:29: error: ‘sigemptyset’ was not declared in this scope
SignalHandlers.cpp:178:19: error: ‘SA_RESTART’ was not declared in this scope
SignalHandlers.cpp:178:32: error: ‘SA_SIGINFO’ was not declared in this scope
SignalHandlers.cpp:181:15: error: ‘SIGSEGV’ was not declared in this scope
SignalHandlers.cpp:181:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:182:15: error: ‘SIGUSR1’ was not declared in this scope
SignalHandlers.cpp:182:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:183:15: error: ‘SIGABRT’ was not declared in this scope
SignalHandlers.cpp:183:33: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:184:15: error: ‘SIGINT’ was not declared in this scope
SignalHandlers.cpp:184:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:185:15: error: ‘SIGBUS’ was not declared in this scope
SignalHandlers.cpp:185:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:186:15: error: ‘SIGSTKFLT’ was not declared in this scope
SignalHandlers.cpp:186:35: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:187:15: error: ‘SIGSYS’ was not declared in this scope
SignalHandlers.cpp:187:32: error: invalid use of incomplete type ‘struct initialise_signal_handlers()::sigaction’
SignalHandlers.cpp:174:12: error: forward declaration of ‘struct initialise_signal_handlers()::sigaction’

g++ 版本:

$ g++ --version
g++ (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3
Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
4

2 回答 2

5

当我不在命令行上使用 -I ... 时,我可以重现您的原始问题。让我翻找一下,看看我能想出什么。

编辑:如果您不更改编译器的 -I (不需要它),那么我认为您需要传递 -m32 (编译为 32 位)或将 REG_EIP 更改为 REG_RIP,因为您(我认为)正在为 64 位编译。

像这样的东西会起作用:

#ifdef __x86_64__
#define REG_EIP REG_RIP
#endif
于 2012-12-23T22:04:39.910 回答
0

您正在为 64 位系统构建,所以REG_EIP不存在。它被替换为REG_RIP

于 2012-12-23T22:11:25.447 回答