有没有比使用 backtrace() 更便宜的方法来查找调用堆栈的深度?
我的日志记录代码使用 backtrace() 的返回值来确定当前堆栈深度(出于漂亮的打印目的),但从分析中我可以看出这是一个相当昂贵的调用。
我不认为有更便宜的方法吗? 请注意,我不关心帧地址,只关心它们有多少。
编辑:这些日志记录函数在大型代码库中使用,因此手动跟踪堆栈深度并不是真正的选择。
My logging code uses the return value of backtrace() to determine the current stack depth (for pretty printing purposes), but I can see from profiling that this is a pretty expensive call.
I don't suppose there's a cheaper way of doing this? Note that I don't care about the frame addresses, just how many of them there are.
edit: These logging functions are used all over a large code-base, so manually tracking the stack depth isn't really an option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
自己遍历堆栈非常快 -
backtrace()
中的大部分缓慢来自于查找符号名称。 在 x86 上,您可以执行以下操作:这将遍历
ebp
指针链。 请记住,这是极其不可移植的。 另请注意,这不会计算任何已内联或尾部调用优化的函数(当然,backtrace()
也有同样的问题)。另一个重要问题是终止条件——一旦回溯到
main()
,通常无法保证您会在堆栈中找到什么。 因此,如果 libc 没有放置空帧指针,则很可能会出现段错误。 您可以通过在main()
的最开头查看它来获取终止值。Walking the stack yourself is pretty quick - most of the slowness in
backtrace()
is from looking up symbol names. On x86, you can do the following:This will walk the chain of
ebp
pointers. Keep in mind that this is extremely non-portable. Also note that this will not count any functions which have been inlined or tail-call optimized (of course,backtrace()
has the same problem).Another important issue is the termination condition -- once you backtrace up to
main()
, there often aren't guarantees about what you'll find in the stack. So, if libc doesn't put a null frame pointer, you'll very likely segfault. You can get the termination value by looking at it at the very beginning ofmain()
.如果合理地包含了漂亮的打印函数,则将缩进(或缩进大小)作为参数传递,并在调用其他显示函数时增加它。
If your pretty-printing functions are reasonably contained, then pass in the indent (or indent size) as a parameter, and just increment it when you call other display functions.
难道你不能随身携带一个名为“深度”的 TLS 变量吗?它/减少它的每个函数? 虽然您可以编写自己的代码来更快地遍历堆栈,但它仍然比随身携带变量要慢。
Can't you just carry a TLS variable around with you called "depth" and increment it / decrement it every function? While you could write your own code to walk the stack quicker, it's still going to be slower than just carrying the variable around with you.
对于arm架构:
For arm architectures :