Boost::堆栈跟踪特定线程



我想调试一个应用程序,其中一些线程在生产环境中似乎陷入死锁(我无法调试,因此我需要一个有意义的日志(。我找到了boost::stacktrace::stacktrack((,但它会转储所有线程的信息。

是否可以将输出限制为特定线程?

如果它是特定于Linux的,则可以使用backtracebacktrace_symbols来检索该特定线程的回溯。

我从man backtrace中修改了这个例子,以包含一个线程。

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <thread>
#define BT_BUF_SIZE 100
void printbt(void)
{
int j, nptrs;
void *buffer[BT_BUF_SIZE];
char **strings;
nptrs = backtrace(buffer, BT_BUF_SIZE);
printf("backtrace() returned %d addressesn", nptrs);
/* The call backtrace_symbols_fd(buffer, nptrs, STDOUT_FILENO)
would produce similar output to the following: */
strings = backtrace_symbols(buffer, nptrs);
if (strings == NULL) {
perror("backtrace_symbols");
exit(EXIT_FAILURE);
}
for (j = 0; j < nptrs; j++)
printf("%sn", strings[j]);
free(strings);
}
static void myfunc2(void)
{
printbt();
}
void myfunc(int ncalls)
{
if (ncalls > 1)
myfunc(ncalls - 1);
else
myfunc2();
}
int main(int argc, char *argv[])
{
if (argc != 2) {
fprintf(stderr, "%s num-callsn", argv[0]);
return 0;
}
std::thread th( myfunc, atoi(argv[1]) );
th.join();
}

你必须用-rdynamic编译才能使用

$ g++ -g3 -rdynamic test2.cpp -o /tmp/test2 -lpthread

运行它提供

$ /tmp/test2 3
backtrace() returned 13 addresses
/tmp/test2(_Z7printbtv+0x32) [0x55e2dbe5d37b]
/tmp/test2(+0x4451) [0x55e2dbe5d451]
/tmp/test2(_Z6myfunci+0x29) [0x55e2dbe5d47d]
/tmp/test2(_Z6myfunci+0x22) [0x55e2dbe5d476]
/tmp/test2(_Z6myfunci+0x22) [0x55e2dbe5d476]
/tmp/test2(_ZSt13__invoke_implIvPFviEJiEET_St14__invoke_otherOT0_DpOT1_+0x36) [0x55e2dbe5e0af]
/tmp/test2(_ZSt8__invokeIPFviEJiEENSt15__invoke_resultIT_JDpT0_EE4typeEOS3_DpOS4_+0x4a) [0x55e2dbe5dffd]
/tmp/test2(_ZNSt6thread8_InvokerISt5tupleIJPFviEiEEE9_M_invokeIJLm0ELm1EEEEvSt12_Index_tupleIJXspT_EEE+0x47) [0x55e2dbe5df4d]
/tmp/test2(_ZNSt6thread8_InvokerISt5tupleIJPFviEiEEEclEv+0x2b) [0x55e2dbe5deef]
/tmp/test2(_ZNSt6thread11_State_implINS_8_InvokerISt5tupleIJPFviEiEEEEE6_M_runEv+0x20) [0x55e2dbe5dec0]
/lib/x86_64-linux-gnu/libstdc++.so.6(+0xd6de4) [0x7f306312ede4]
/lib/x86_64-linux-gnu/libpthread.so.0(+0x8609) [0x7f3063242609]
/lib/x86_64-linux-gnu/libc.so.6(clone+0x43) [0x7f3062f6a133]

您可以使用__cxa_deangle来自动解映射符号,也可以简单地使用gcc中的c++filt

$ echo _ZSt13__invoke_implIvPFviEJiEET_St14__invoke_otherOT0_DpOT1_+0x36 | c++filt
void std::__invoke_impl<void, void (*)(int), int>(std::__invoke_other, void (*&&)(int), int&&)+0x36
$ echo _Z6myfunci+0x29 | c++filt
myfunc(int)+0x29

然后,您可以进入gdb,查看函数myfunc(int)中偏移0x29对应的行