Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to know what function called another

I wanna know if there is any way to know where the function currently in execution was called, this is, in what file and line. I'm using C language, and I'm looking for something similar to __FUNCTION__, __LINE__ or __FILE__ macros.

like image 708
Sérgio Avatar asked Jul 26 '10 18:07

Sérgio


4 Answers

Rename your function

void Function(param1)
{
}

to

void Function_debug(param1, char * file, char * func, unsigned long line)
{
}

Then #define a macro like this:

#define Function(param1) Function_debug(param1, __FILE__, __FUNCTION__, __LINE__)
like image 97
bits Avatar answered Nov 10 '22 05:11

bits


There's nothing in C itself that would give you this information. You could either trace the information yourself (upon entry/exit) or rely on platform specific APIs to walk the call stack and determine the calling function, but not much more.

like image 38
Assaf Lavie Avatar answered Nov 10 '22 06:11

Assaf Lavie


__FILE__, __LINE__ etc are preprocessor macros which can easily be expanded to the correct value at compile time. A function may get called from many possible places, so that can't be done via the preprocessor. Finding out the caller's name would be very difficult; it involves walking the stack and matching addresses to symbols.

If you can live with a small hack, this might work (untested):

/* Add a called argument to your function */
void _myFunction(char *caller, int more_args)

/* And define a macro that adds it automagically */
#define myFunction(a) _myFunction(__FUNCTION__, a)
like image 2
Matti Virkkunen Avatar answered Nov 10 '22 04:11

Matti Virkkunen


There isn't anything that is supported in all implementations that will do what you want. I have occasionally found myself in the same situation, where I needed to track callers for a few methods and did something like the following:

#ifdef TRACKBACK
int foo(int arg1, int arg2, const char * file, int line)
{
    SEND_TO_LOG("foo", file, line);
#else
int foo(int arg1, int arg2)
{
#endif
    ...
    ...

Of course, it makes for a bit of a headache at the calling end, so you'll want to do something like:

#ifdef TRACKBACK
    #define TRACKING, __FILE__, __LINE__
#else
    #define TRACKING
#endif

Then the call:

foo(arg1, arg2 TRACKING);  //note the lack of the comma

It does the trick when all else fails.

like image 1
Sniggerfardimungus Avatar answered Nov 10 '22 04:11

Sniggerfardimungus