views:

264

answers:

6

Is there any way to dump the call stack in a running process in C or C++ every time a certain function is called? What I have in mind is something like this:

void foo()
{
   print_stack_trace();

   // foo's body

   return
}

Where print_stack_trace works similarly to caller in Perl.

Or something like this:

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

    // etc...
}

where register_stack_trace_function puts some sort of internal breakpoint that will cause a stack trace to be printed whenever foo is called.

Does anything like this exist in some standard C library?

I am working on Linux, using GCC.


Background

I have a test run that behaves differently based on some commandline switches that shouldn't affect this behavior. My code has a pseudo-random number generator that I assume is being called differently based on these switches. I want to be able to run the test with each set of switches and see if the random number generator is called differently for each one.

A: 

Is there any way to dump the call stack in a running process in C or C++ every time a certain function is called?

No there is not, although platform-dependent solutions might exist.

sbi
+8  A: 

For a linux-only solution you can use backtrace(3) that simply returns an array of void * (in fact each of these point to the return address from the corresponding stack frame). To translate these to something of use, there's backtrace_symbols(3).

Pay attention to the notes section in backtrace(3):

The symbol names may be unavailable without the use of special linker options. For systems using the GNU linker, it is necessary to use the -rdynamic linker option. Note that names of "static" functions are not exposed, and won't be available in the backtrace.

Idan K
+1  A: 

You can implement the functionality yourself:

Use a global (string)stack and at start of each function push the function name and such other values (eg parameters) onto this stack; at exit of function pop it again.

Write a function that will printout the stack content when it is called, and use this in the function where you want to see the callstack.

This may sound like a lot of work but is quite useful.

slashmais
I would not do that. Rather, I'd create a wrapper which uses the underlying platform specific APIs (see below). The amount of work would be probably the same, but the investment should pay off faster.
paul_71
@paul: your answer refers to windows when the OP clearly specifies linux ... but could be useful for windows-guys who show up here.
slashmais
Right, I overlooked that..Hm, it's the last sentence of the question, so maybe the poster should modify his request to mention his/her target platform in a more prominent place.
paul_71
This would be a good idea, except my codebase includes a few dozen files containing a few hundred (if not a few thousand) files, so this is unfeasible.
Nathan Fellman
maybe not if you hack-up a sed/perl script to add after each function declaration `call_registror MY_SUPERSECRETNAME(__FUNCTION__);` which pushes the argument in its constructor and pops in its destructor __FUNCTION__ always represents the name of the current function.
flownt
slashmais
+1  A: 

There is no standardized way to do that. For windows the functionality is provided in the DbgHelp library

paul_71
+1  A: 

Of course the next question is: will this be enough ?

The main disadvantage of stack-traces is that why you have the precise function being called you do not have anything else, like the value of its arguments, which is very useful for debugging.

If you have access to gcc and gdb, I would suggest using assert to check for a specific condition, and produce a memory dump if it is not met. Of course this means the process will stop, but you'll have a full fledged report instead of a mere stack-trace.

If you wish for a less obtrusive way, you can always use logging. There are very efficient logging facilities out there, like Pantheios for example. Which once again could give you a much more accurate image of what is going on.

Matthieu M.
Of course it may not be enough, but if I can see that the function is called in place with one configuration and not with the other, then that's a pretty good place to start.
Nathan Fellman
A: 

You can use the GNU profiler. It shows the call-graph as well! the command is gprof. and you need to compile ur code with some option.

Saurabh Shah