Reputation: 12307
I have been using __PRETTY_FUNCTION__
to output the current function name, however I have reimplemented some functions and would like to find out which functions are calling them.
In C++ how can I get the function name of the calling routine?
Upvotes: 61
Views: 107849
Reputation: 8958
#include <iostream>
#include <source_location>
void some_function(std::source_location fun = std::source_location::current())
{
std::cout << fun.function_name() << "\n";
}
void some_other_function()
{
some_function();
}
int main()
{
some_other_function();
}
void __cdecl some_other_function(void)
Upvotes: 2
Reputation: 38667
Combining __builtin_return_address and dladdr works in C++, C, Objective-C and Objective-C++:
#include <dlfcn.h>
Dl_info info;
if (dladdr(__builtin_return_address(0), &info)) {
printf("%s called by %s", __builtin_FUNCTION(), info.dli_sname);
}
Note that dladdr
requires a dynamically linked programs:
To link your program dynamically, you might need to add -rdynamic
or -Wl,--export-dynamic
as an option (source).
Upvotes: 0
Reputation: 3814
Here is a solution you can often use. It has the advantage of requiring no changes to the actual function code (no adding calls to stackwalk functions, changing parameters to pass in function names, or linking to extra libraries.). To get it working, you simply need to use a bit of preprocessor magic:
// orignal function name was 'FunctionName'
void FunctionNameReal(...)
{
// Do Something
}
#undef FunctionName
#define FunctionName printf("Calling FunctionName from %s\n",__FUNCTION__);FunctionNameReal
You must rename your function temporarily, but see the note below for more suggestions. This will result in a printf()
statement at each point of calling the function. Obviously, you have to make some arrangements if you are calling a member function, or need to capture the return value (Like pass the function call and __FUNCTION__
to a custom function that returns the same type...), but the basic technique is the same. You might want to use __LINE__
and __FILE__
or some other preprocessor macros depending on which compiler you have. (This example is specifically for MS VC++, but probably works in others.)
Also, you might want to put something like this in your header surrounded by #ifdef
guards to conditionally turn it on, which can handle renaming the actual function for you as well.
I got a request to expand my answer. As it turns out, my above example is a bit simplistic. Here are some fully compiling examples of handling this, using C++.
Using a class
with operator()
makes this pretty straight forward. This first technique works for freestanding functions with and without return values. operator()
just needs to reflect the same return as the function in question, and have matching arguments.
You can compile this with g++ -o test test.cpp
for a non-reporting version and g++ -o test test.cpp -DREPORT
for a version that displays the caller information.
#include <iostream>
int FunctionName(int one, int two)
{
static int calls=0;
return (++calls+one)*two;
}
#ifdef REPORT
// class to capture the caller and print it.
class Reporter
{
public:
Reporter(std::string Caller, std::string File, int Line)
: caller_(Caller)
, file_(File)
, line_(Line)
{}
int operator()(int one, int two)
{
std::cout
<< "Reporter: FunctionName() is being called by "
<< caller_ << "() in " << file_ << ":" << line_ << std::endl;
// can use the original name here, as it is still defined
return FunctionName(one,two);
}
private:
std::string caller_;
std::string file_;
int line_;
};
// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of Reporter initialized with the caller
# undef FunctionName
# define FunctionName Reporter(__FUNCTION__,__FILE__,__LINE__)
#endif
void Caller1()
{
int val = FunctionName(7,9); // <-- works for captured return value
std::cout << "Mystery Function got " << val << std::endl;
}
void Caller2()
{
// Works for inline as well.
std::cout << "Mystery Function got " << FunctionName(11,13) << std::endl;
}
int main(int argc, char** argv)
{
Caller1();
Caller2();
return 0;
}
Sample Output (Reporting)
Reporter: FunctionName() is being called by Caller1() in test.cpp:44
Mystery Function got 72
Reporter: FunctionName() is being called by Caller2() in test.cpp:51
Mystery Function got 169
Basically, anywhere that FunctionName
occurs, it replaces it with Reporter(__FUNCTION__,__FILE__,__LINE__)
, the net effect of which is the preprocessor writing some object instancing with an immediate call to the operator()
function. You can view the result (in gcc) of the preprocessor substitutions with g++ -E -DREPORT test.cpp
. Caller2() becomes this:
void Caller2()
{
std::cout << "Mystery Function got " << Reporter(__FUNCTION__,"test.cpp",51)(11,13) << std::endl;
}
You can see that __LINE__
and __FILE__
have been substituted. (I'm not sure why __FUNCTION__
still shows in the output to be honest, but the compiled version reports the right function, so it probably has something to do with multi-pass preprocessing or a gcc bug.)
This is a bit more complicated, but very similar to the previous example. Instead of just replacing the call to the function, we are also replacing the class.
Like the above example, you can compile this with g++ -o test test.cpp
for a non-reporting version and g++ -o test test.cpp -DREPORT
for a version that displays the caller information.
#include <iostream>
class ClassName
{
public:
explicit ClassName(int Member)
: member_(Member)
{}
int FunctionName(int one, int two)
{
return (++member_+one)*two;
}
private:
int member_;
};
#ifdef REPORT
// class to capture the caller and print it.
class ClassNameDecorator
{
public:
ClassNameDecorator( int Member)
: className_(Member)
{}
ClassNameDecorator& FunctionName(std::string Caller, std::string File, int Line)
{
std::cout
<< "Reporter: ClassName::FunctionName() is being called by "
<< Caller << "() in " << File << ":" << Line << std::endl;
return *this;
}
int operator()(int one, int two)
{
return className_.FunctionName(one,two);
}
private:
ClassName className_;
};
// remove the symbol for the function, then define a new version that instead
// creates a stack temporary instance of ClassNameDecorator.
// FunctionName is then replaced with a version that takes the caller information
// and uses Method Chaining to allow operator() to be invoked with the original
// parameters.
# undef ClassName
# define ClassName ClassNameDecorator
# undef FunctionName
# define FunctionName FunctionName(__FUNCTION__,__FILE__,__LINE__)
#endif
void Caller1()
{
ClassName foo(21);
int val = foo.FunctionName(7,9); // <-- works for captured return value
std::cout << "Mystery Function got " << val << std::endl;
}
void Caller2()
{
ClassName foo(42);
// Works for inline as well.
std::cout << "Mystery Function got " << foo.FunctionName(11,13) << std::endl;
}
int main(int argc, char** argv)
{
Caller1();
Caller2();
return 0;
}
Here is sample output:
Reporter: ClassName::FunctionName() is being called by Caller1() in test.cpp:56
Mystery Function got 261
Reporter: ClassName::FunctionName() is being called by Caller2() in test.cpp:64
Mystery Function got 702
The high points of this version are a class that decorates the original class, and a replacement function that returns a reference to the class instance, allowing the operator()
to do the actual function call.
Upvotes: 62
Reputation: 11
Cflow can be used to get the call graph of the source code written in C/C++. You can parse this call graph to get what you want.
Upvotes: -1
Reputation: 9418
Variation of Aaron answer. I am not sure whether this answer has this problem, but when you do a #define function
, it becomes a global variable, then, if your project has several classes with the same member class function name, all classes will have their function name redefined to the same function.
#include <iostream>
struct ClassName {
int member;
ClassName(int member) : member(member) { }
int secretFunctionName(
int one, int two, const char* caller, const char* file, int line)
{
std::cout << "Reporter: ClassName::function_name() is being called by "
<< caller << "() in " << file << ":" << line << std::endl;
return (++member+one)*two;
}
};
#define unique_global_function_name(first, second) \
secretFunctionName(first, second, __FUNCTION__,__FILE__,__LINE__)
void caller1() {
ClassName foo(21);
int val = foo.unique_global_function_name(7, 9);
std::cout << "Mystery Function got " << val << std::endl;
}
void caller2() {
ClassName foo(42);
int val = foo.unique_global_function_name(11, 13);
std::cout << "Mystery Function got " << val << std::endl;
}
int main(int argc, char** argv) {
caller1();
caller2();
return 0;
}
Result:
Reporter: ClassName::function_name() is being called by caller1() in D:\test.cpp:26
Mystery Function got 261
Reporter: ClassName::function_name() is being called by caller2() in D:\test.cpp:33
Mystery Function got 702
Upvotes: 3
Reputation: 179779
You probably want the names of all functions that potentially could call them. This is basically a set of edges in the call graph. doxygen can generate the call graph, and then it's simply a matter of looking at the incoming edges of your functions node.
Upvotes: 1
Reputation: 1518
You can use this code, to track loci of control in last n points in your program. Usage: see main function below.
// What: Track last few lines in loci of control, gpl/moshahmed_at_gmail
// Test: gcc -Wall -g -lm -std=c11 track.c
#include <stdio.h>
#include <string.h>
#define _DEBUG
#ifdef _DEBUG
#define lsize 255 /* const int lsize=255; -- C++ */
struct locs {
int line[lsize];
char *file[lsize];
char *func[lsize];
int cur; /* cur=0; C++ */
} locs;
#define track do {\
locs.line[locs.cur]=__LINE__ ;\
locs.file[locs.cur]=(char*)__FILE__ ;\
locs.func[locs.cur]=(char*) __builtin_FUNCTION() /* __PRETTY_FUNCTION__ -- C++ */ ;\
locs.cur=(locs.cur+1) % lsize;\
} while(0);
void track_start(){
memset(&locs,0, sizeof locs);
}
void track_print(){
int i, k;
for (i=0; i<lsize; i++){
k = (locs.cur+i) % lsize;
if (locs.file[k]){
fprintf(stderr,"%d: %s:%d %s\n",
k, locs.file[k],
locs.line[k], locs.func[k]);
}
}
}
#else
#define track do {} while(0)
#define track_start() (void)0
#define track_print() (void)0
#endif
// Sample usage.
void bar(){ track ; }
void foo(){ track ; bar(); }
int main(){
int k;
track_start();
for (k=0;k<2;k++)
foo();
track;
track_print();
return 0;
}
Upvotes: 1
Reputation: 891
With GCC version ≥ 4.8 you can use __builtin_FUNCTION
— not to be confused with __FUNCTION__
and similar — it seems to be a bit obscure.
Example:
#include <cstdio>
void foobar(const char* str = __builtin_FUNCTION()){
std::printf("called by %s\n", str);
}
int main(){
foobar();
return 0;
}
output:
called by main
Upvotes: 41
Reputation: 59807
Here are two options:
You can get a full stacktrace (including the name, module, and offset of the calling function) with recent versions of glibc with the GNU backtrace functions. See my answer here for the details. This is probably the easiest thing.
If that isn't exactly what you're looking for, then you might try libunwind, but it's going to involve more work.
Keep in mind that this isn't something you can know statically (as with PRETTY_FUNCTION); you actually have to walk the stack to figure out what function called you. So this isn't something that's really worth doing in ordinary debug printfs. If you want to do more serious debugging or analysis, though, then this might be useful for you.
Upvotes: 30
Reputation: 213
Unless there is more to the question than you explicitly asked, just rename the function and let the compiler/linker tell you where it is called.
Upvotes: 4
Reputation:
In the firs approximation, just grep the codebase for the function names. Then comes Doxygen, and then dynamic logging (both discussed by others).
Upvotes: 1