本文介绍的这种方式通过c语言中的execinfo.h头文件的两个函数,backtrace和backtrace_symbols_fd来完成该任务。该方式只是生成一个error文件,该error文件中包含的就是栈信息。
首先要加上信号异常时的handler进行捕捉,如下
signal(SIGSEGV, SignalHandler);
也就是发生段错误时,会调用SignalHandler这个函数,这个函数可以这么写
void *array[50];
time_t cur_time;
struct tm *tblock;
char buf[50];
cur_time = time(NULL);
sprintf(buf, "%lld", cur_time);
string error_log = string("error.log") + buf;
size_t size;
int fd = open(error_log.c_str(), O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
sprintf(buf, "In signal handler function, the signal is %d\n", sig);
write(fd, buf, strlen(buf));
size = backtrace(array, 50);
backtrace_symbols_fd(array, size, fd);
close(fd);
signal(sig, SIG_DFL);
对error文件加上了timestamp以做区分。我们看一下某一个error文件的内容如下
1 ./Searcher[0x49b276]
2 /lib64/libc.so.6[0x3d69c302d0]
3 ./Searcher[0x412458]
4 ./Searcher[0x425229]
5 ./Searcher[0x4261f0]
6 ./Searcher[0x42dfe4]
7 ./Searcher[0x49d805]
8/lib64/libpthread.so.0[0x3d6a806617]
9/lib64/libc.so.6(clone+0x6d)[0x3d69cd3c2d]
用addr2line命令来分析(-e 后面是执行文件, -f表示打印函数信息),如:[zhangle@localhost env]$ addr2line 0x49b276-e Searcher -f
_ZN7CDaemon13SignalHandlerEi
??:0
[zhangle@localhost env]$ addr2line 0x412458-e Searcher -f
_ZN9CSearcher18SearchAllTextFieldERSt6vectorIP10CTextQuerySaIS2_EERS0_I7SResultSaIS6_EER7CBitMapbim
??:0
[zhangle@localhost env]$ addr2line 0x425229-e Searcher -f
_ZN9CSearcher8MatchDocERSt6vectorIP10CTextQuerySaIS2_EERS0_IP6CQuerySaIS7_EERS0_I7SResultSaISB_EEiP7CModule
??:0
[zhangle@localhost env]$ addr2line 0x4261f0-e Searcher -f
_ZN9CSearcher6SearchERN9__gnu_cxx8hash_mapISsSsNS0_4hashISsEESt8equal_toISsESaISsEEERSsR11ConnectInfo
??:0
[zhangle@localhost env]$ addr2line 0x42dfe4-e Searcher -f
_ZN9CSearcher13HandleRequestERSsS0_R11ConnectInfo
??:0
[zhangle@localhost env]$ addr2line 0x49d805-e Searcher -f
_ZN12CServerFrame12ServerThreadEPv:w
标红的就是函数信息。这样我们知道是CSearcher::SearchAllTextField函数除了问题。