在某些多路径的函数(例如退出),我们希望通过在日志中打印堆栈,确认调用途径,以定位一些奇怪的业务逻辑问题。
在Linux中,我们可以使用backtrace函数进行追踪。
*Android不支持此方法
1.使用示例
*以下代码节选自backtrace的man
int j, nptrs;
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, 100);
strings = backtrace_symbols(buffer, nptrs);
if (strings != NULL)
{
for (j = 0; j < nptrs; j++)
printf("%s\n",strings[j]);
free(strings);
}
打印结果示例
lib/libpt.so.2.12.8(_ZN7PThread9TerminateEv+0x106) [0x7ffff783e932]
lib/libpt.so.2.12.8(_ZN8PProcess11PreShutdownEv+0x31b) [0x7ffff78696e9]
lib/libpt.so.2.12.8(_ZN8PProcessD1Ev+0x82) [0x7ffff783f422]
/opt/code/server_cloud/pkg/H323Gateway(_ZN8CMainAppD1Ev+0x35) [0x4d3ee9]
/opt/code/server_cloud/pkg/H323Gateway(_ZN8CMainAppD0Ev+0x18) [0x4d3f18]
/opt/code/server_cloud/pkg/H323Gateway(H323GW_UnInit+0x39) [0x4f8e98]
/opt/code/server_cloud/pkg/H323Gateway(main+0x28) [0x4f8ecd]
/lib64/libc.so.6(__libc_start_main+0xf5) [0x7ffff4f46505]
/opt/code/server_cloud/pkg/H323Gateway() [0x4be389]
2. 进阶玩法-崩溃时自动打印堆栈
在某些特殊情况下,我们无法生成CORE(可能是存储空间问题,或者其他问题);那么可以借用这个代码,简单定位一些明显的逻辑问题
void OnCrash(int nSig)
{
switch (nSig)
{
case SIGFPE:
printf("%s\n", "Program Crashed with SIGFPE: ");
break;
case SIGSEGV:
printf("%s\n", "Program Crashed with SIGSEGV: ");
break;
case SIGBUS:
printf("%s\n", "Program Crashed with SIGBUS: ");
break;
}
int j, nptrs;
void *buffer[100];
char **strings;
nptrs = backtrace(buffer, 100);
strings = backtrace_symbols(buffer, nptrs);
if (strings != NULL)
{
for (j = 0; j < nptrs; j++)
printf("%s\n", strings[j]);
free(strings);
}
signal(SIGSEGV, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGBUS, SIG_DFL);
raise(SIGQUIT); // Dump core
_exit(-1); // Fail safe if raise() didn't dump core and exit
}
int main(int argc, char** argv)
{
//……
//也可以不在main中,在其他初始化必然经过的代码中
signal(SIGSEGV, OnCrash);
signal(SIGFPE, OnCrash);
signal(SIGBUS, OnCrash);
//……
}
3. 常见问题
-
Q:我的打印中只显示了地址,没有显示具体的函数名,是怎么回事?
A:需要在CFLAGS参数中,增加 -rdynamic -
Q:我还想知道具体的行号,怎么处理?
A:可以将最后方括号里面的函数地址,用addr2line函数配套EXE来解决。此方法同样可以解决没有打印具体函数名时的排查问题。
示例:
addr2line --exe=H323Gateway -i 0x4f8e98
结果:
/opt/code/server_cloud/applications/h323gw/main.cpp:85 (discriminator 1)