【问题标题】:Get the call stack in code with less overhead?以更少的开销获取代码中的调用堆栈?
【发布时间】:2009-08-05 07:29:02
【问题描述】:

我将在 linux 上为内存实现一个内部分析器。我想为每个 malloc/free/realloc 保存堆栈。我每次都尝试使用“pstack”来获取堆栈跟踪。但是开销太高了。是否有任何轻量级的方法来获取 C 代码中的调用堆栈?

我知道有一些工具,例如“valgrind,google profiler”,但不知道它们如何记住每个操作的堆栈。

欢迎评论。

谢谢。

【问题讨论】:

  • 把你的“问题”改写成一个真正的问题怎么样?
  • 您可以随时查看 valgrinds 源代码。 [valgrind.org/downloads/]
  • 已编辑。很抱歉描述不清楚。
  • 是的。我将从 valgrind 的源代码中得到一些东西。

标签: c linux profiler


【解决方案1】:

有一个 GNU 函数 backtrace() 相对较快 - 它只返回地址数组。

要将这些地址解析为函数名称,您需要使用 backtrace_symbols(),它要重得多,但希望您不需要太频繁地运行它。

要获得backtrace_symbols() 实际解析名称,您需要使用-rdynamic 链接器选项。

详情请见man backtrace

【讨论】:

    【解决方案2】:

    您可以制作自己的函数来获取调用者:

    static inline void *get_caller(void) {
        unsigned long *ebp;
    
        /* WARNING: This is working only with frame pointers */
        asm ("movl %%ebp, %0" : "=r" (ebp) : );
        ebp = (unsigned long*)*ebp;
        ebp = (unsigned long*)*(ebp+1);
        return ebp;
    }
    
    void *malloc(void) {
        void *caller = get_caller();
        ...    
    }
    

    "ebp = (unsigned long*)*ebp;" 将使您遍历堆栈(如果您需要更多堆栈跟踪)。

    【讨论】:

      【解决方案3】:

      注意使用 backtrace_symbols() 的递归,它调用 malloc 本身。

      还要注意,在第一次使用 backtrace() 和朋友时,动态链接器将尝试加载 libgcc,这将再次调用 malloc。

      吉拉德

      【讨论】:

        【解决方案4】:

        现在我在 64 位上遇到了问题。

        在 64 位上,RBP 没有得到严格维护。例如, gcc -O3 将使用 RBP 作为普通调用者保存的寄存器。所以在这种情况下,从帧指针获取调用堆栈是行不通的。:(

        有没有cmets?

        【讨论】:

        • 在 64 位上,现在我正在使用 backtrace()
        猜你喜欢
        • 2022-11-22
        • 1970-01-01
        • 2018-01-20
        • 2020-09-02
        • 2011-11-21
        • 1970-01-01
        • 2018-06-22
        • 1970-01-01
        • 2011-05-03
        相关资源
        最近更新 更多