C++ 名称空间中的stacktrace和函数
我试图在(c++程序)执行的某个点上获得回溯 为此,我使用了回溯和回溯符号。大致如下:C++ 名称空间中的stacktrace和函数,c++,gcc,g++,backtrace,C++,Gcc,G++,Backtrace,我试图在(c++程序)执行的某个点上获得回溯 为此,我使用了回溯和回溯符号。大致如下: std::string stacktrace( unsigned int frames_to_skip ) { std::string str; void* stack_addrs[50]; int trace_size = backtrace( stack_addrs, 50 ); char** stack_strings = backtrace_symbols( stac
std::string stacktrace( unsigned int frames_to_skip )
{
std::string str;
void* stack_addrs[50];
int trace_size = backtrace( stack_addrs, 50 );
char** stack_strings = backtrace_symbols( stack_addrs, trace_size );
str += "[bt] backtrace:\n";
// skip frames_to_skip stack frames
for( int i = frames_to_skip; i < trace_size; ++i )
{
char tmp[4096];
sprintf( tmp, "[bt] #%d %s\n", i-frames_to_skip, stack_strings[i] );
str += tmp;
}
free( stack_strings );
return str;
}
函数0到8有一个共同点:它们都位于名称空间中…我试着将函数9放在一个匿名名称空间中(没有任何其他修改),它从回溯中消失了。。。现在看起来是这样的:
[bt] #0 /path/to/executable() [0x43e1b5]
[bt] #1 /path/to/executable() [0x43e0cd]
[bt] #2 /path/to/executable() [0x43df51]
[bt] #3 /path/to/executable() [0x43dd44]
[bt] #4 /path/to/executable() [0x43db50]
[bt] #5 /path/to/executable() [0x43d847]
[bt] #6 /path/to/executable() [0x43d216]
[bt] #7 /path/to/executable() [0x43c1e1]
[bt] #8 /path/to/executable() [0x43b293]
[bt] #9 /path/to/executable() [0x43a6ca]
[bt] #10 /path/to/executable(_Z11SomeIN5_8symbolEPFvRS1_EEvRKT_RKT0_+0x77) [0x441716]
...
有没有办法解决这个问题
p、 美国:g++的版本:
g++(GCC)4.6.0 20110530(红帽4.6.0-9)
编辑修复了代码猴子备注后回溯的最大深度edit2添加了函数的完整代码
edit3代码是用-O0-g3编译的,并与-rdynamic链接您的问题可能是您正在使用的函数。
回溯(..
)中的max_depth
设置为16
。这可能太低了。无论如何
上的这篇博文解释了应该如何执行堆栈跟踪。总之
#include <execinfo.h>
void print_trace(FILE *out, const char *file, int line)
{
const size_t max_depth = 100;
size_t stack_depth;
void *stack_addrs[max_depth];
char **stack_strings;
stack_depth = backtrace(stack_addrs, max_depth);
stack_strings = backtrace_symbols(stack_addrs, stack_depth);
fprintf(out, "Call stack from %s:%d:\n", file, line);
for (size_t i = 1; i < stack_depth; i++) {
fprintf(out, " %s\n", stack_strings[i]);
}
free(stack_strings); // malloc()ed by backtrace_symbols
fflush(out);
}
#包括
无效打印跟踪(文件*输出,常量字符*文件,整数行)
{
const size\u t max\u depth=100;
尺寸、堆叠深度;
void*堆栈地址[最大深度];
字符**堆栈_字符串;
堆栈深度=回溯(堆栈地址,最大深度);
堆栈字符串=回溯符号(堆栈地址、堆栈深度);
fprintf(out,“来自%s的调用堆栈:%d:\n”,文件,行);
对于(大小i=1;i<堆栈深度;i++){
fprintf(out,“%s\n”,堆栈_字符串[i]);
}
free(stack_strings);//malloc()由回溯_符号指定
(外);;
}
GCC还提供对C++名称(DE)MangLever的访问。有一些 关于内存所有权和接口的详细信息 对于堆栈跟踪输出,需要进行一些字符串解析,但是 归结起来就是用以下内容替换上述内部循环:
#包括
...
对于(大小i=1;i
该站点上有更多信息(我不想逐字复制),但是查看此代码和上面的站点应该会让您走上正确的轨道。您可以尝试将-rdynamic添加到您的链接中吗
backtrace
列出了调用帧,它对应于机器代码调用
指令,而不是源代码级函数调用
不同之处在于,使用内联,优化编译器通常可以避免对源代码中的每个逻辑函数调用使用
调用
指令。您好,谢谢您的回答。关于最大深度,您是对的,回溯的结尾缺失,但这不是问题,因为这些缺失的调用来自测试fra我正在使用的mework。但是,问题仍然存在,我正在做博客文章中所说的相同的事情。然而,一个有趣的事实是,测试框架在名称空间中确实有函数,它们在stacktrace中可见,我的函数不是……我再次进行了测试(将函数放入名称空间),同样的结果再次出现(该函数在回溯中不再可见……在这种情况下,它们根本不会出现在bt中。无论如何,这里没有优化,它是用-O0-g3
编译的。此外,如果我打断构造回溯的函数,并在反汇编视图中转到不带符号的一下的地址(我正在使用eclipse),我在正确显示的调用
指令之后结束(aka显示它将跳入的函数/方法的名称)。
#include <execinfo.h>
void print_trace(FILE *out, const char *file, int line)
{
const size_t max_depth = 100;
size_t stack_depth;
void *stack_addrs[max_depth];
char **stack_strings;
stack_depth = backtrace(stack_addrs, max_depth);
stack_strings = backtrace_symbols(stack_addrs, stack_depth);
fprintf(out, "Call stack from %s:%d:\n", file, line);
for (size_t i = 1; i < stack_depth; i++) {
fprintf(out, " %s\n", stack_strings[i]);
}
free(stack_strings); // malloc()ed by backtrace_symbols
fflush(out);
}
#include <cxxabi.h>
...
for (size_t i = 1; i < stack.depth; i++) {
size_t sz = 200; // just a guess, template names will go much wider
char *function = static_cast(malloc(sz));
char *begin = 0, *end = 0;
// find the parentheses and address offset surrounding the mangled name
for (char *j = stack.strings[i]; *j; ++j) {
if (*j == '(') {
begin = j;
}
else if (*j == '+') {
end = j;
}
}
if (begin && end) {
*begin++ = '';
*end = '';
// found our mangled name, now in [begin, end)
int status;
char *ret = abi::__cxa_demangle(begin, function, &sz, &status);
if (ret) {
// return value may be a realloc() of the input
function = ret;
}
else {
// demangling failed, just pretend it's a C function with no args
std::strncpy(function, begin, sz);
std::strncat(function, "()", sz);
function[sz-1] = '';
}
fprintf(out, " %s:%s\n", stack.strings[i], function);
}
else
{
// didn't find the mangled name, just print the whole line
fprintf(out, " %s\n", stack.strings[i]);
}
free(function);
}