用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可能存在。