在代码中以较少的开销获取调用堆栈?

时间:2009-08-05 07:29:02

标签: c linux profiler

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

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

任何评论都表示赞赏。

感谢。

4 个答案:

答案 0 :(得分:4)

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

要将这些地址解析为函数名称,您需要使用backtrace_symbols()这个更重,但希望您不需要经常运行它。

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

有关详细信息,请参阅man backtrace

答案 1 :(得分: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;”会让你通过堆栈(如果你需要更多的堆栈跟踪)。

答案 2 :(得分:0)

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

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

吉拉德

答案 3 :(得分:0)

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

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

有任何意见吗?