【问题标题】:Is there a way to get function name inside a C++ function?有没有办法在 C++ 函数中获取函数名?
【发布时间】:2010-10-18 11:56:33
【问题描述】:

我想实现一个函数跟踪器,它会跟踪一个函数执行的时间。我有以下相同的课程:-

class FuncTracer
{
    public:
        FuncTracer(LPCTSTR strFuncName_in)
        {
            m_strFuncName[0] = _T('\0');
            if( strFuncName_in ||
                _T('\0') != strFuncName_in[0])
            {   
                _tcscpy(m_strFuncName,strFuncName_in);

                TCHAR strLog[MAX_PATH];
                _stprintf(strLog,_T("Entering Func:- <%s>"),m_strFuncName);
                LOG(strLog)

                m_dwEnterTime = GetTickCount();
            }
        }

        ~FuncTracer()
        {
            TCHAR strLog[MAX_PATH];
            _stprintf(strLog,_T("Leaving Func:- <%s>, Time inside the func <%d> ms"),m_strFuncName, GetTickCount()-m_dwEnterTime);
            LOG(strLog)
        }

    private:
        TCHAR m_strFuncName[MAX_PATH];
        DWORD m_dwEnterTime;
};

void TestClass::TestFunction()
{
    // I want to avoid writing the function name maually..
    // Is there any macro (__LINE__)or some other way to 
    // get the function name inside a function ??

    FuncTracer(_T("TestClass::TestFunction"));
    /*
     * Rest of the function code.
     */
}

我想知道是否有任何方法可以从函数内部获取函数的名称?基本上我希望我的班级的用户简单地创建一个相同的对象。他们可能不会传递函数名。

【问题讨论】:

    标签: c++ macros profiling


    【解决方案1】:

    C++20 std::source_location::function_name

    这基本上完全符合您的要求。

    https://en.cppreference.com/w/cpp/utility/source_location 声明用法如下:

    #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 main() {
        log("Hello world!");
    }
    

    可能的输出:

    info:main.cpp:16:main Hello world!
    

    因此请注意呼叫如何保留呼叫者信息,因此我们会看到所需的 main 呼叫位置而不是 log

    我已经更详细地介绍了相关标准:What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?

    【讨论】:

    • 虽然如果您点击链接到参考,它显示有一个 function_name 字段,我不认为代码的副本和可能的输出提供了很大的价值,因为它没有提到它。它只是参考中内容的副本,无论如何您都必须单击参考以获取与此问题相关的信息。指向您的其他 SO 答案的链接更有帮助,因为该答案至少提到了 function_name 字段。
    【解决方案2】:

    C99 有 __func__,但对于 C++,这将是特定于编译器的。从好的方面来说,一些特定于编译器的版本提供了额外的类型信息,这在您在模板化函数/类中进行跟踪时特别好。

    • MSVC: __FUNCTION__, __FUNCDNAME__, __FUNCSIG__
    • GCC__func____FUNCTION____PRETTY_FUNCTION__

    Boost 库在头文件 boost/current_function.hpp 中为大多数 C++ 编译器定义了宏 BOOST_CURRENT_FUNCTION。如果编译器太旧而无法支持此功能,则结果将为“(未知)”。

    【讨论】:

      【解决方案3】:

      我本来想说我不知道​​这样的事情,但后来我看到了其他答案......

      您可能会感兴趣的是,执行分析器(如 gprof)完全按照您的要求执行 - 它跟踪执行每个函数所花费的时间。分析器的工作原理是每隔 10 毫秒左右记录一次指令指针 (IP)、当前执行指令的地址。程序运行完毕后,您调用一个后处理器来检查 IP 列表和程序,并将这些地址转换为函数名称。所以我建议只使用指令指针,而不是函数名,因为它更容易编码,而且使用单个数字比使用字符串更有效。

      【讨论】:

      • 请注意,要执行此操作,您还必须保存可执行文件/库的图像加载地址,否则您可能无法有意义地解释记录的地址。此外,编译器对自定义分析器的支持(例如 MSVC 中的 _penter/_pexit)可以替代定期采样。
      【解决方案4】:

      VC++有

      __FUNCTION__ for undecorated names
      

      __FUNCDNAME__ for decorated names
      

      您可以编写一个宏,它自己会分配一个对象,并在构造函数中传递名称转换宏。有点喜欢

      #define ALLOC_LOGGER FuncTracer ____tracer( __FUNCTION__ );
      

      【讨论】:

      • 什么不起作用?编译器无法识别宏还是什么?
      • 是的。在 VC6 中编译时,它说 FUNCTION 作为未声明的标识符。是我遗漏了什么还是不受支持?
      • 看起来 VC6 不支持它 - codeguru.com/forum/showthread.php?threadid=385694 这很不幸,但你应该查看 VC6 手册 - 也许还有其他类似的宏。
      • @Trevor Boyd Smith:OP 提供了使用 Win32 特定定义的代码,这几乎总是暗示 MSVC。
      • @codetaku 源代码使用 Windows SDK typedefs。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-02-17
      • 1970-01-01
      • 2013-02-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-30
      相关资源
      最近更新 更多