Reputation: 11957
After years of using the big ugly MFC ASSERT macro, I have finally decided to ditch it and create the ultimate ASSERT macro.
I am fine with getting the file and line number, and even the expression that failed. I can display a messagebox with these in, and Abort/Retry/Cancel buttons.
And when I press Retry the VS debugger jumps to the line containing the ASSERT call (as opposed to the disassembly somewhere like some other ASSERT functions). So it's all pretty much working.
But what would be really cool would be to display the name of the function that failed.
Then I can decide whether to debug it without trying to guess what function it's in from the filename.
e.g. if I have the following function:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ASSERT(lpCreateStruct->cx > 0);
...
}
Then when the ASSERT fires, the messagebox would show something like:
Function = CMainFrame::OnCreate
So, what's the simplest way of finding out the current function name, at runtime?
It should not use MFC or the .NET framework, even though I do use both of these.
It should be as portable as possible.
Upvotes: 47
Views: 67948
Reputation: 13786
There's no standard solution. However, BOOST_CURRENT_FUNCTION
is portable for all practical purposes. The header does not not depend on any of the other Boost headers, so can be used standalone if the overhead of the whole library is unacceptable.
Upvotes: 19
Reputation: 382472
C++20 std::source_location::function_name
No macros are needed now that we have proper standardization:
main.cpp
#include <iostream>
#include <string_view>
#include <source_location>
void log(std::string_view message,
const std::source_location& location = std::source_location::current()
) {
std::cout << "info:"
<< location.file_name() << ":"
<< location.line() << ":"
<< location.function_name() << " "
<< message << '\n';
}
int f(int i) {
log("Hello world!"); // Line 16
return i + 1;
}
int f(double i) {
log("Hello world!"); // Line 21
return i + 1.0;
}
int main() {
f(1);
f(1.0);
}
Compile and run:
g++ -ggdb3 -O0 -std=c++20 -Wall -Wextra -pedantic -o source_location.out source_location.cpp
./source_location.out
Output:
info:source_location.cpp:16:int f(int) Hello world!
info:source_location.cpp:21:int f(double) Hello world!
so note how the call preserves caller information, so we see the desired main
call location instead of log
.
I have covered the relevant standards in a bit more detail at: What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?
Tested on Ubuntu 22.04, GCC 11.3.
Upvotes: 7
Reputation: 2192
The C++ preprocessor macro __FUNCTION__
gives the name of the function.
Note that if you use this, it's not really getting the filename, line number, or function name at runtime. Macros are expanded by the preprocessor, and compiled in.
Example program:
#include <iostream>
void function1()
{
std::cout << "my function name is: " << __FUNCTION__ << "\n";
}
int main()
{
std::cout << "my function name is: " << __FUNCTION__ << "\n";
function1();
return 0;
}
output:
my function name is: main my function name is: function1
Upvotes: 28
Reputation: 1308
you can easily use func. it will take back you current function name at runtime which raised the exception.
usage:
cout << __func__ << ": " << e.what();
Upvotes: 1
Reputation: 58786
You can use the __FUNCTION__
macro which at compile time will be expanded to the name of the function.
Here's an example of how to use it in an assert macro.
#define ASSERT(cond) \
do { if (!(cond)) \
MessageBoxFunction("Failed: %s in Function %s", #cond, __FUNCTION__);\
} while(0)
void MessageBoxFunction(const char* const msg, ...)
{
char szAssertMsg[2048];
// format args
va_list vargs;
va_start(vargs, msg);
vsprintf(szAssertMsg, msg, vargs);
va_end(vargs);
::MessageBoxA(NULL, szAssertMsg, "Failed Assertion", MB_ICONERROR | MB_OK);
}
Upvotes: 5
Reputation: 4569
__FUNCTION__
or __FUNC__
or __PRETTY_FUNCTION__
http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
Upvotes: 11
Reputation: 38869
In GCC you can use the __PRETTY_FUNCTION__
macro.
Microsoft also have an equivalent __func__
macro although I don't have that available to try.
e.g. to use __PRETTY_FUNCTION__
putting something like this at the beginning of your functions and you'll get a complete trace
void foo(char* bar){
cout << __PRETTY_FUNCTION__ << std::endl
}
which will output
void foo(char* bar)
You also have the __FILE__
and __LINE__
macros available under all standard c/c++ compilers if you want to output even more information.
In practice I have a special debugging class which I use instead of cout. By defining appropriate environment variables I can get a full program trace. You could do something similar. These macros are incredibly handy and it's really great to be able to turn on selective debugging like this in the field.
EDIT: apparently __func__
is part of the standard? didn't know that. Unfortunately, it only gives the function name and not the parameters as well. I do like gcc's __PRETTY_FUNC__
but it's not portable to other compilers.
GCC also supports __FUNCTION__
.
Upvotes: 10
Reputation: 75913
Your macro can contain the __FUNCTION__
macro.
Make no mistake, the function name will be inserted into the expanded code at compile time, but it will be the correct function name for each call to your macro. So it "seems like" it happens in run-time ;)
e.g.
#define THROW_IF(val) if (val) throw "error in " __FUNCTION__
int foo()
{
int a = 0;
THROW_IF(a > 0); // will throw "error in foo()"
}
Upvotes: 60