用C或C ++打印调用堆栈

每次调用某个函数时,有没有办法在C或C ++的运行进程中转储调用堆栈? 我想到的是这样的:

void foo() { print_stack_trace(); // foo's body return } 

print_stack_trace与Perl中的caller类似。

或者像这样的东西:

 int main (void) { // will print out debug info every time foo() is called register_stack_trace_function(foo); // etc... } 

其中register_stack_trace_function放置了某种内部断点,当调用foo时会导致打印堆栈跟踪。

在一些标准的C库中是否存在这样的事情?

我正在使用GCC在Linux上工作。


背景

我有一个testing运行的行为不同,基于一些命令行开关,不应该影响这种行为。 我的代码有一个伪随机数生成器,我假设这些开关的调用是不同的。 我希望能够用每一组开关来运行testing,看看每一个随机数发生器是不同的。

对于仅用于linux的解决scheme,您可以使用backtrace(3) ,它仅返回一个void *数组(实际上每个指向相应的堆栈帧的返回地址)。 为了将这些翻译成使用的东西,有backtrace_symbols(3) 。

注意回溯(3)中的注释部分 :

没有使用特殊的链接器选项,符号名称可能不可用。 对于使用GNU链接器的系统,有必要使用-rdynamic链接器选项。 请注意,“静态”函数的名称没有公开,并且在回溯中不可用。

没有标准的方法来做到这一点。 对于Windows, DbgHelp库提供了该function

每次调用某个函数时,有没有办法在C或C ++的运行进程中转储调用堆栈?

您可以使用macros函数而不是特定函数中的return语句。

例如,而不是使用返回,

 int foo(...) { if (error happened) return -1; ... do something ... return 0 } 

你可以使用macrosfunction。

 #include "c-callstack.h" int foo(...) { if (error happened) NL_RETURN(-1); ... do something ... NL_RETURN(0); } 

每当函数发生错误时,您将看到如下所示的Java样式的调用堆栈。

 Error(code:-1) at : so_topless_ranking_server (sample.c:23) Error(code:-1) at : nanolat_database (sample.c:31) Error(code:-1) at : nanolat_message_queue (sample.c:39) Error(code:-1) at : main (sample.c:47) 

完整的源代码可在这里。

c-callstack在https://github.com/Nanolat

你可以使用这个罂粟 。 它通常用于在崩溃期间收集堆栈跟踪,但也可以将其输出到正在运行的程序中。

现在有一个很好的部分:它可以输出堆栈中每个函数的实际参数值,甚至是局部variables,循环计数器等等。

你可以自己实现这个function:

使用全局(string)堆栈,并在每个函数开始时将函数名称和其他值(例如参数)推送到此堆栈; 在function退出时再次popup。

编写一个函数,在调用堆栈内容时打印输出内容,并在要查看调用堆栈的函数中使用该函数。

这可能听起来像很多工作,但是非常有用。

当然,接下来的问题是:这样就够了吗?

栈跟踪的主要缺点是,为什么你有精确的函数被调用,你没有其他的东西,比如它的参数的值,这对debugging非常有用。

如果你有权访问gcc和gdb,我会build议使用assert来检查一个特定的条件,如果不符合,会产生一个内存转储。 当然,这意味着这个过程将停止,但是你将拥有一个完整的报告,而不是一个简单的堆栈跟踪。

如果你希望不那么突兀的方式,你总是可以使用日志logging。 有非常有效的日志logging设施,例如Pantheios 。 这再一次可以给你一个更准确的形象正在发生的事情。

你可以使用GNU分析器。 它也显示了调用图! 该命令是gprof ,你需要用一些选项编译你的代码。

每次调用某个函数时,有没有办法在C或C ++的运行进程中转储调用堆栈?

没有,虽然依赖于平台的解决scheme可能存在。