有没有办法在C ++函数中获取函数名?

时间:2009-04-09 06:33:30

标签: c++ macros profiling

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

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.
     */
}

我想知道是否有办法从函数内部获取函数的名称?基本上我希望我班级的用户只需创建一个相同的对象。它们可能无法传递函数名称。

4 个答案:

答案 0 :(得分:51)

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

  • MSVC__FUNCTION____FUNCDNAME____FUNCSIG__
  • GCC__func____FUNCTION____PRETTY_FUNCTION__

Boost库为标题boost/current_function.hpp中的大多数C ++编译器定义了宏BOOST_CURRENT_FUNCTION。如果编译器太旧而无法支持,那么结果将是“(未知)”。

答案 1 :(得分:21)

VC ++有

__FUNCTION__ for undecorated names

__FUNCDNAME__ for decorated names

你可以编写一个宏,它本身会分配一个对象并在构造函数中传递name-yelding宏。像Smth一样

#define ALLOC_LOGGER FuncTracer ____tracer( __FUNCTION__ );

答案 2 :(得分:6)

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!

因此请注意呼叫如何保留呼叫者信息。

我已经在What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?

上详细介绍了相关标准。

答案 3 :(得分:3)

我打算说我不知道​​任何这样的事情,但后来我看到了其他答案......

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