Linux开发之崩溃处理

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 

你可能感兴趣的:(Linux开发之崩溃处理)