命名空间中的堆栈跟踪和函数
我试图在我的(c++)程序执行的某个时刻获得回溯。
为此,我使用 backtrace 和 backtrace_symbols。类似的事情:
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;
}
它可以工作,但缺少一些函数名称。示例:
[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(_Z29SomeRN5other8symbolE+0x2c) [0x43a6ca]
[bt] #10 /path/to/executable(_Z11SomeIN5_8symbolEPFvRS1_EEvRKT_RKT0_+0x77) [0x441716]
...
函数 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]
...
有什么方法可以解决这个问题吗?
ps:g++版本: g++ (GCC) 4.6.0 20110530 (Red Hat 4.6.0-9)
编辑修复了 Code Monkey 备注后回溯的最大深度
edit2添加了函数的完整代码
edit3 代码使用 -O0 -g3 编译并使用 -rdynamic 链接
I am trying to get a backtrace at some point of the execution of my (c++) program.
for that I am using backtrace and backtrace_symbols. Something along this lines:
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;
}
It works but some functions names are missing. example:
[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(_Z29SomeRN5other8symbolE+0x2c) [0x43a6ca]
[bt] #10 /path/to/executable(_Z11SomeIN5_8symbolEPFvRS1_EEvRKT_RKT0_+0x77) [0x441716]
...
the functions 0 to 8 have one common point : they all sit in a namespace...
I tried putting function 9 in an anonymous namespace (without any other modification) and it disapears from the backtrace... which now looks like this:
[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]
...
Is there any way to fix that?
p.s.: version of g++:
g++ (GCC) 4.6.0 20110530 (Red Hat 4.6.0-9)
edit fixed max depth of the backtrace after Code Monkey remark
edit2 added the full code of the function
edit3 the code is compiled with -O0 -g3 and linked with -rdynamic
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您的问题可能是您正在使用的功能。
backtrace(..
) 中的max_depth
设置为16
。这可能太低了。无论如何...这篇关于 C++ 堆栈的博客文章Traces with GCC 解释了应该如何执行堆栈跟踪。总而言之,
该网站上有更多信息(我不想逐字复制),但是查看此代码和上面的网站应该会让您走上正确的轨道。
Your problem may be the functions you are using. Your
max_depth
inbacktrace(..
) is set to16
. That may be too low. At any rate...This blog post on C++ stack traces with GCC explains how you should be performing stack traces. In sum,
There is more information on that site (I didn't want to copy verbatim) but looking at this code and the above site should get you on the right track.
您可以尝试将 -rdynamic 添加到您的链接吗?
http://www.linuxforums.org/forum/programming -scripting/35192-backtrace_symbols-no-symbols.html
Can you try adding -rdynamic to your link?
http://www.linuxforums.org/forum/programming-scripting/35192-backtrace_symbols-no-symbols.html
backtrace
列出了调用帧,它们对应于机器代码call
指令,而不是源级别的函数调用。不同之处在于,通过内联,优化编译器通常可以避免对源代码中的每个逻辑函数调用使用
call
指令。backtrace
lists the call frames, which correspond to machine codecall
instructions, not source level function calls.The difference is that with inlining, an optimizing compiler can often avoid using a
call
instruction for every logical function call in the source code.