Linux开发之崩溃处理
注册信号的处理函数EnableCrashHandler
崩溃处理函数OnCrashHandler
代码如下:
#include
#include
#include
#include
#include
#include
#ifdef __linux
#include
#endif // __linux
const int MAX_STACK_FRAMES = 32;
void OnCrashHandler(int signum)
{
FILE* f = fopen("log/crash.txt","at");
if(nullptr == f)
{
exit(1);
return;
}
try
{
char szLine[512]= {0,};
time_t t = time(nullptr);
tm* now = localtime(&t);
int nLen1 = sprintf(szLine
,"#########################################################\n[%04d-%02d-%02d %02d:%02d:%02d][crash signal number:%d]\n"
,now->tm_year + 1900
,now->tm_mon + 1
,now->tm_mday
,now->tm_hour
,now->tm_min
,now->tm_sec
,signum);
fwrite(szLine,1,strlen(szLine),f);
#ifdef __linux
void* array[MAX_STACK_FRAMES];
size_t size = 0;
char** strings = nullptr;
size_t i,j;
signal(signum,SIG_DFL);
size = backtrace(array,MAX_STACK_FRAMES);
strings =(char**)backtrace_symbols(array,size);
//fprintf(stderr,"oncrash;\n");
for(i = 0;i < size;++i)
{
#if 0
std::string symbol(strings[i]);
std::string::size_type pos1 = symbol.find_first_of("[");
std::string::size_type pos2 = symbol.find_last_of("]");
std::string address = symbo.substr(pos1 + 1,pos2 - pos1 -1);
char cmd[128]= {0,};
sprintf(cmd,"addr2line -e gameserver %p",address.c_str());
system(cmd);
#endif
char szLine[512]= {0,};
sprintf(szLine,"%d %s\n",i,strings[i]);
fwrite(szLine,1,strlen(szLine),f);
// fprintf(stderr,"%d %s\n",i,strings[i]);
}
free(strings);
#endif // __linux
}
catch(...)
{
//
}
fflush(f);
fclose(f);
f = nullptr;
exit(1);
}
void EnableCrashHandler()
{
#ifdef __linux
signal(SIGSEGV,OnCrashHandler);
signal(SIGABRT,OnCrashHandler);
#endif // __linux
}
在代码中添加上述代码
2
编译
编译时要加上-g和-rdynamic两个参数,如:g++ main.cpp -o testdump -g -std=c++11 -rdynamic
注意:
不加-g,addr2line程序无法打印行号;
不加-rdynamic,backtrace无法打印完整信息,可能会没有和函数名称相关的信息;
如果是ARM平台arm-linux-gcc交叉编译,需要带如下编译参数-funwind-tables -ffunction-sections
否则可能backtrace返回值为0,得不到需要的信息。
3
使用 Addr2line 将函数地址解析为函数名
Addr2line
工具(它是标准的 GNU Binutils 中的一部分)是一个可以将指令的地址和可执行映像转换成文件名、函数名和源代码行数的工具。这种功能对于将跟踪地址转换成更有意义的内容来说简直是太棒了。注意编译程序时需要添加-g选项才可以,也可以添加-Wl 和-map选项。在调用 Addr2line 工具时,要使用 -e 选项来指定可执行映像是 test。通过使用 -f 选项,可以告诉工具输出函数名。例如:addr2line 0x08048258 -e test -f