suppose i have 3 functions:
a()
b()
and c()
both a() and b() can called c(). if function c() is called how do i know who is the caller??

Dani AI

Generated

Short answer: let the caller tell the callee who it is (the portable, maintainable solution). As pointed out, a callee normally should not need to know its caller. 's wrapper/parameter idea is the simplest and most robust; 's debug macros are a good debug-only option. Below are safe alternatives and the trade-offs if runtime detection inside the callee is still required.

For quick diagnostics (Linux/glibc): capture the current stack with the execinfo API (backtrace / backtrace_symbols) and resolve addresses to source lines with addr2line. This works well for logging in debug builds if you compile with debug symbols and export symbols (for example -g -rdynamic). See the glibc backtraces documentation and the addr2line manual for details. ()

If you want a cheaper peek at the immediate caller address, GCC exposes the built-ins __builtin_return_address and __builtin_frame_address which return return/frame addresses (use only for debugging and be careful with levels > 0). Combine those addresses with dladdr() to map an address to a symbol. For global instrumentation you can compile with -finstrument-functions and implement the __cyg_profile_func_enter/exit hooks to build a call tree at runtime. On Windows, the supported APIs are CaptureStackBackTrace / StackWalk64. See the GCC and Windows docs and dladdr man page for the mechanics and examples. (gcc.gnu.org)

Important caveats: compiler optimizations (inlining, tail-call elimination, frame-pointer omission) and differing ABIs make stack inspection fragile or impossible in optimized builds. These techniques are non-portable and best restricted to debug builds or off-line postprocessing. If you use a macro-based call-tree recorder (like suggested), make the counters/storage thread-local (_Thread_local / thread_local / __thread) for multi-threaded programs to avoid races. For production behavior, the cleanest approach is an explicit caller/context parameter or a logging hook. ()

Quick debug workflow (no code duplication of thread posts):

gcc -g -rdynamic -O0 -o prog prog.c
# run prog; have it call backtrace() and print addresses
addr2line -e prog 0xADDRESS_FROM_BACKTRACE

References: glibc backtraces, GNU addr2line, GCC return-address and instrumentation docs, Windows stack-capture docs, dladdr man page, and C11 thread-local docs. ()

Recommended Answers

All 4 Replies

You dont', and you shouldn't. c() should not care who called it, but just do its job and return the results (if any) to the caller.

actually i just made a code in which i need to know who's the caller but later i managed the alternate way to solve my problem.
but still i wanna know whos is the caller..???

You can pass the name of the caller into the callee:

void a(const char *caller)
{
    printf("%s called from %s\n", __func__, caller);
}

void b(const char *caller)
{
    printf("%s called from %s\n", __func__, caller);
    a(__func__);
}

int main(void)
{
    b(__func__);
    return 0;
}

The above code uses C99's predefined __func__ for simplicity. In compilers that don't support it, you'll have to come up with your own naming convention and pass string literals.

There are techniques for building a call-tree by judicious use of macros, so in your code you can do something like this:

#ifdef DEBUG
#define MAX_TREE_DEPTH 10000
size_t ct_level = 0;
const char* call_tree[MAX_TREE_DEPTH];

#define CALLTREE_ENTER call_tree[ct_level++] = __func__;
#define CALLTREE_EXIT  call_tree[ct_level--] = 0;
#else
#define CALLTREE_ENTER
#define CALLTREE_EXIT
#endif /* DEBUG */

void a(void)
{
#ifdef DEBUG
  printf("a() called from %s\n", call_tree[ct_level - 1]);
#endif
}


void b(void)
{
#ifdef DEBUG
  printf("b() called from %s\n", call_tree[ct_level - 1]);
#endif

  CALLTREE_ENTER
  a();
  CALLTREE_EXIT
}

int main(void)
{
   CALLTREE_ENTER
   b();
   CALLTREE_EXIT
   return 0;
}

Now, if you haven't compiled your code for debugging, this will have no performance impact upon you, but if you did, you get the call tree output.

I leave it as an exercise to the poster to add the macro needed so you can eliminate the #ifdef DEBUG blocks in the functions, so you could do something like this:

PRINT_CALLER(__func__);

instead if debugging is on.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.