How do I get the name of the calling function?

后端 未结 3 505
广开言路
广开言路 2021-02-04 03:38

I am using gnu tool chain. How can I, at run time, find caller of a function? i.e for example function B() gets called by many functions using function pointers. Now, whenever B

相关标签:
3条回答
  • 2021-02-04 04:21

    If you're using GNU, you can use the backtrace functions. There's an example of the use on that man page.

    0 讨论(0)
  • 2021-02-04 04:35

    Another method, pointed out by Vasil Dimov in answer to a similar question, is to replace the function call with a wrapper macro that reports or passes in the calling function name. This will work with inline functions, where backtrace won't. On the other hand it won't work if you call the function by reference, or otherwise take its address.

    For example this:

    int B(int x){
        ...
    }
    

    could become:

    int _B(int x, char *caller){
        printf("caller is %s\n", caller);
        ...
    }
    
    #define B(x) _B((x), __func__)
    

    and every call to B() will print the callers name. Vasil Dimov constructs it differently, printing the name directly in the macro and leaving the function unchanged.

    0 讨论(0)
  • 2021-02-04 04:36

    The code location of the call to your function is kept by gcc in the __builtin_return_address() intrinsic. To retrieve the name for that, you have to parse the program's symbol table; while that is possible to do, via dladdr(), there are limits to this:

    1. it might not be safe in all contexts to call backtrace()/dladdr() (like, from signal handlers, or concurrently in a multithreaded program, or from contexts where you can't call malloc().).
    2. the operation is not instant but might require putting the calling thread to sleep; this is a bad thing if at the point of the call any locks are held.
    3. there's limits to how well "resolvable" a return address is into a name; e.g. if there are inlined functions calling your function then the caller of your caller would show up (the backtrace() manpage states this as well, as does the one for dladdr() in the "BUGS" section).
    4. In C++, there's the additional challenge of calls through con/destructors/initializers, where the "caller" of your function may end up being some compiler-generated metacode, and the actual place you're interested in could be elsewhere (caller of caller, or even deeper in the call stack).

    It's often a better way to decouple tracing and function name resolving; i.e. just output the return addresses (as hex / binary) and then postprocess the resulting log against a symbol table retrieved when the program was running.

    0 讨论(0)
提交回复
热议问题