2012-03-04 63 views
11

我的问题与此SO post和一些其他alike有关。我想知道调用者函数的名称,因为在声明失败时,我不知道哪个函数将垃圾值传递给被调用者。一种方法是检查所有可以调用此函数的函数,但这非常麻烦。跟踪断言失败时如何知道来电函数

即使依赖于平台,您是否可以提出更好的解决方案?我正在使用g ++ 4.6。提前致谢。

+1

你就不能在调试器中看到的堆栈跟踪运行的程序? – sth 2012-03-04 14:56:34

+3

有很多使用情况下,你不能这样做 – Coren 2012-03-04 15:03:30

回答

2

参见backtrace()

例如

#include <execinfo.h> 
#include <stdio.h> 

void bar() { 
    void* callstack[128]; 
    int i, frames = backtrace(callstack, 128); 
    char** strs = backtrace_symbols(callstack, frames); 
    for (i = 0; i < frames; ++i) { 
    printf("%s\n", strs[i]); 
    } 
    free(strs); 
} 

int foo() { 
    bar(); 
    return 0; 
} 

int main() { 
    foo(); 
    return 0; 
} 

输出:

0 a.out        0x0000000100000e24 bar + 28 
1 a.out        0x0000000100000e81 foo + 14 
2 a.out        0x0000000100000e96 main + 14 
3 a.out        0x0000000100000e00 start + 52 
4 ???         0x0000000000000001 0x0 + 1 

参见:

How to generate a stacktrace when my gcc C++ app crashes

4

您在glibc中有backtrace函数。它可以让你有完整的跟踪,调用者函数或方法。

如果只想来电,这里还有specific functionsGCC只是这样的:

__builtin_frame_address(int level); 

随着level == 1你有来电的功能。有关如何使用它的更多详细信息,请参见this post

下面是示例程序,它是在文档中:

#include <execinfo.h> 
#include <stdio.h> 
#include <stdlib.h> 

/* Obtain a backtrace and print it to stdout. */ 
void 
print_trace (void) 
{ 
    void *array[10]; 
    size_t size; 
    char **strings; 
    size_t i; 

    size = backtrace (array, 10); 
    strings = backtrace_symbols (array, size); 

    printf ("Obtained %zd stack frames.\n", size); 

    for (i = 0; i < size; i++) 
    printf ("%s\n", strings[i]); 

    free (strings); 
} 

/* A dummy function to make the backtrace more interesting. */ 
void 
dummy_function (void) 
{ 
    print_trace(); 
} 

int 
main (void) 
{ 
    dummy_function(); 
    return 0; 
} 
+0

我发现它也便于发出'backtrace'本身的结果(原始指针)。然后你可以使用'addr2line'命令行工具将它转换为实际的源文件名和行号。 – 2012-03-04 14:59:36

+0

非常感谢。但如何获取函数的名称?这似乎只打印一些地址。请原谅我的无知。 – user984260 2012-03-04 15:00:36

+0

在字符串[i]中,您有函数名称和其他链接的dlinfo,它甚至可以向您显示更多信息 – Coren 2012-03-04 15:02:35