此代码始终无法在 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.