经过多年使用丑陋的MFC ASSERT宏之后,我终于决定抛弃它并创建最终的ASSERT宏。
我可以获取文件和行号,甚至是失败的表达式。我可以显示带有这些内容的消息框,以及中止/重试/取消按钮。
当我按下Retry时,VS调试器会跳转到包含ASSERT调用的行(而不像某些其他ASSERT函数那样反汇编)。所以这一切都非常有用。
但真正酷的是显示失败的功能的名称。
然后我可以决定是否调试它而不试图从文件名中猜出它的功能。
e.g。如果我有以下功能:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ASSERT(lpCreateStruct->cx > 0);
...
}
然后当ASSERT触发时,消息框将显示如下内容:
Function = CMainFrame::OnCreate
那么,在运行时找出当前函数名的最简单方法是什么?
它不应该使用MFC或.NET框架,即使我同时使用这两者 它应该尽可能便携。
答案 0 :(得分:51)
您的宏可以包含__FUNCTION__
宏。
毫无疑问,函数名称将插入到编译时的扩展代码中,但对于每次调用宏,它都是正确的函数名。所以它“似乎”在运行时发生;)
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()"
}
答案 1 :(得分:23)
C ++预处理器宏__FUNCTION__
给出了函数的名称。
请注意,如果您使用此功能,则确实在运行时获取文件名,行号或函数名称。宏由预处理器扩展,并在。
中编译 __FUNCTION__
宏,如__LINE__
和__FILE__
,是语言标准的一部分,可以移植。
示例程序:
#include <iostream>
#using namespace std;
void function1()
{
cout << "my function name is: " << __FUNCTION__ << "\n";
}
int main()
{
cout << "my function name is: " << __FUNCTION__ << "\n";
function1();
return 0;
}
输出:
my function name is: main my function name is: function1
答案 2 :(得分:18)
没有标准的解决方案。但是,BOOST_CURRENT_FUNCTION
可用于所有实际目的。标头不依赖于任何其他Boost标头,因此如果整个库的开销是不可接受的,可以单独使用。
答案 3 :(得分:10)
__FUNCTION__
或__FUNC__
或__PRETTY_FUNCTION__
http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
答案 4 :(得分:8)
在GCC中,您可以使用__PRETTY_FUNCTION__
宏
微软也有一个等效的__func__
宏,虽然我没有可用的。
e.g。使用__PRETTY_FUNCTION__
在函数的开头放置这样的东西,你就可以获得完整的跟踪
void foo(char* bar){
cout << __PRETTY_FUNCTION__ << std::endl
}
将输出
void foo(char* bar)
如果您想输出更多信息,还可以在所有标准c / c ++编译器下使用__FILE__
和__LINE__
个宏。
在实践中,我有一个特殊的调试类,我使用它而不是cout。通过定义适当的环境变量,我可以获得完整的程序跟踪。你可以做类似的事情。这些宏非常方便,能够在现场打开这样的选择性调试真的很棒。
编辑:显然__func__
是标准的一部分?不知道那个。不幸的是,它只提供函数名称而不是参数。我喜欢gcc的__PRETTY_FUNC__
,但它不能移植到其他编译器。
GCC还支持__FUNCTION__
。
答案 5 :(得分:5)
您可以使用__FUNCTION__
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);
}
答案 6 :(得分:0)
您可以轻松使用 func 。 它将在运行时收回您当前的函数名称,从而引发异常。
用法:
cout << __func__ << ": " << e.what();