如何在运行时找到当前函数的名称?
在使用又大又丑的 MFC ASSERT 宏多年之后,我终于决定放弃它并创建终极的 ASSERT 宏。
我可以很好地获取文件和行号,甚至失败的表达式。 我可以显示一个消息框,其中包含中止/重试/取消按钮。
当我按“重试”时,VS 调试器会跳转到包含 ASSERT 调用的行(而不是像其他 ASSERT 函数那样进行反汇编)。 所以这一切都非常有效。
但真正酷的是显示失败函数的名称。
然后我可以决定是否调试它,而无需尝试从文件名猜测它的函数。
例如,如果我有以下函数:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ASSERT(lpCreateStruct->cx > 0);
...
}
那么当 ASSERT 触发时,消息框将显示类似以下内容:
Function = CMainFrame::OnCreate
那么,在运行时查找当前函数名称的最简单方法是什么?
它应该不使用 MFC 或 .NET 框架,尽管我确实使用了这两个框架。
它应该尽可能便携。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
在 GCC 中,您可以使用
__PRETTY_FUNCTION__
宏。微软也有一个等效的
__func__
宏,尽管我没有可以尝试。例如,使用
__PRETTY_FUNCTION__
在函数的开头放置类似的内容,您将获得完整的跟踪,该跟踪将输出
您还拥有
__FILE__
和__LINE__<如果您想输出更多信息,/code> 宏可在所有标准 c/c++ 编译器下使用。
在实践中,我有一个特殊的调试类,我用它来代替 cout。 通过定义适当的环境变量,我可以获得完整的程序跟踪。 你可以做类似的事情。 这些宏非常方便,能够在现场像这样打开选择性调试真是太棒了。
编辑:显然
__func__
是标准的一部分? 我不知道。 不幸的是,它只给出了函数名称,而没有给出参数。 我确实喜欢 gcc 的__PRETTY_FUNC__
但它不能移植到其他编译器。GCC 还支持
__FUNCTION__
。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 tracewhich will output
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__
.您可以使用
__FUNCTION__
宏 在编译时将扩展为函数的名称。下面是如何在断言宏中使用它的示例。
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.
C++20
std::source_location::function_name
现在我们已经有了适当的标准化,所以不需要宏:
main.cpp
编译并运行:
输出:
所以请注意如何调用保留调用者信息,因此我们看到所需的
main
调用位置而不是log
。我在以下位置更详细地介绍了相关标准: __PRETTY_FUNCTION__、__FUNCTION__、__func__ 之间有什么区别?
在 Ubuntu 22.04、GCC 11.3 上测试。
C++20
std::source_location::function_name
No macros are needed now that we have proper standardization:
main.cpp
Compile and run:
Output:
so note how the call preserves caller information, so we see the desired
main
call location instead oflog
.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.
您可以轻松使用func。
它会在运行时取回引发异常的当前函数名称。
用法:
you can easily use func.
it will take back you current function name at runtime which raised the exception.
usage:
您的宏可以包含
__FUNCTION__
宏。毫无疑问,函数名称将在编译时插入到扩展代码中,但对于每次调用宏来说,它将是正确的函数名称。 所以它“看起来”是在运行时发生的;)
例如
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.
C++ 预处理器宏
__FUNCTION__
给出了函数的名称。请注意,如果您使用此方法,它实际上并不能在运行时获取文件名、行号或函数名称。 宏由预处理器扩展并编译。
示例程序:
输出:
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:
output:
没有标准的解决方案。 但是,
BOOST_CURRENT_FUNCTION
对于所有实际目的都是可移植的。 该标头不依赖于任何其他 Boost 标头,因此如果整个库的开销不可接受,则可以独立使用。
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.__FUNCTION__
或__FUNC__
或__PRETTY_FUNCTION__
http://msdn.microsoft.com/en-us/library/b0084kay(VS.80).aspx
http://gcc.gnu.org/onlinedocs/gcc/Function-Names。 html
__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