20

My question is related to this SO post and some others alike. I wanted to know the name of caller function, since at the time of assertion failure, I don't know which function passed a garbage value to callee. One method is to put check in all the functions which could call this function, but that is very cumbersome.

Can you suggest a better solution, even though platform-dependent? I am using g++ 4.6. Thanks in advance.

Community
  • 1
  • 1
user984260
  • 3,401
  • 5
  • 25
  • 38

2 Answers2

9

See backtrace().

e.g.

#include <execinfo.h>
#include <stdio.h>

void bar() {
  void* callstack[128];
  int i, frames = backtrace(callstack, 128);
  char** strs = backtrace_symbols(callstack, frames);
  for (i = 0; i < frames; ++i) {
    printf("%s\n", strs[i]);
  }
  free(strs);
}

int foo() {
  bar();
  return 0;
}

int main() {
  foo();
  return 0;
}

Output:

0   a.out                               0x0000000100000e24 bar + 28
1   a.out                               0x0000000100000e81 foo + 14
2   a.out                               0x0000000100000e96 main + 14
3   a.out                               0x0000000100000e00 start + 52
4   ???                                 0x0000000000000001 0x0 + 1

See:

How to generate a stacktrace when my gcc C++ app crashes

Community
  • 1
  • 1
Manish
  • 3,472
  • 1
  • 17
  • 16
5

You have backtrace functions in glibc. It can allow you to have full trace, with the caller function or method.

If you only want the caller, there's also specific functions in gcc just for this :

__builtin_frame_address(int level);

With level == 1 you have the caller function. See this post for more detail about how to use it.

Here is the sample program which is in the documentation :

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>

/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
  void *array[10];
  size_t size;
  char **strings;
  size_t i;

  size = backtrace (array, 10);
  strings = backtrace_symbols (array, size);

  printf ("Obtained %zd stack frames.\n", size);

  for (i = 0; i < size; i++)
     printf ("%s\n", strings[i]);

  free (strings);
}

/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
  print_trace ();
}

int
main (void)
{
  dummy_function ();
  return 0;
}
Coren
  • 5,517
  • 1
  • 21
  • 34
  • I find it convenient to also emit the results of `backtrace` itself (the raw pointers). You can then use the `addr2line` command-line utility to convert it to actual source file names and line numbers. – edA-qa mort-ora-y Mar 04 '12 at 14:59
  • Thanks a lot. But how to get the name of the function? This only seems to print some addresses. Pardon my ignorance. – user984260 Mar 04 '12 at 15:00
  • In strings[i], you have functions name and with dlinfo of the other link, it can even show you more information – Coren Mar 04 '12 at 15:02