有没有比使用backtrace()更便宜的方法来find调用堆栈的深度?

我的日志logging代码使用backtrace()的返回值来确定当前的堆栈深度(用于漂亮的打印目的),但从分析中可以看出这是一个相当昂贵的调用。

我不认为有这样做的更便宜的方法? 请注意,我不关心帧地址,只是其中有多less。

编辑:这些日志loggingfunction遍布大型代码库,所以手动跟踪堆栈深度并不是一个真正的select。

自行走栈非常快 – backtrace()大部分缓慢来自查找符号名称。 在x86上,您可以执行以下操作:

 inline uint32_t get_ebp(void) { __asm__ __volatile__("mov %%ebp, %%eax"); } int get_stack_depth(void) { uint32_t ebp = get_ebp(); int stack_depth = 0; while(ebp != 0) { ebp = *(uint32_t *)ebp; stack_depth++; } return stack_depth; } 

这将走ebp指针链。 请记住,这是非常不便携的。 另外请注意,这不会计算任何内联或尾调优化的函数(当然, backtrace()也有同样的问题)。

另一个重要的问题是终止条件 – 一旦你回溯到main() ,通常不能保证你能在栈中找到什么。 所以,如果libc没有放置空帧指针,那么很可能会出现段错误。 您可以通过在main()开头查看终止值。

如果你的漂亮打印函数被合理地包含,那么传入缩进(或缩进大小)作为参数,并在调用其他显示函数时递增。

难道你不能随身携带一个名为“深度”的TLS变量,并增加/减少每一个函数吗? 虽然你可以编写你自己的代码来更快地执行堆栈,但是它还是会比只是随身携带变量慢。

对于手臂架构:

 register unsigned long *rfp asm("fp"); unsigned long *fp = rfp; unsigned long depth = 0; while(fp) { fp = (unsigned long *)(*(fp -3)); depth++; } return depth;