web-dev-qa-db-ja.com

C ++関数内で関数名を取得する方法はありますか?

関数の実行にかかる時間を追跡する関数トレーサーを実装したいと思います。私は同じために次のクラスを持っています:-

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

関数の内部から関数の名前を取得する方法があるかどうか知りたいですか?基本的には、クラスのユーザーが同じオブジェクトを作成することを望んでいます。関数名を渡さない場合があります。

26
Canopus

VC++は

__FUNCTION__ for undecorated names

そして

__FUNCDNAME__ for decorated names

そして、それ自体がオブジェクトを割り当て、コンストラクタ内で名前を付けるマクロを渡すマクロを書くことができます。 Smthのような

#define ALLOC_LOGGER FuncTracer ____tracer( __FUNCTION__ );
23
sharptooth

C99には__func__がありますが、C++の場合、これはコンパイラー固有です。プラス面として、コンパイラ固有のバージョンの一部は、追加の型情報を提供します。これは、テンプレート化された関数/クラス内をトレースしているときに特に便利です。

Boostライブラリは、ヘッダー boost/current_function.hpp のほとんどのC++コンパイラ用にマクロBOOST_CURRENT_FUNCTIONを定義しています。コンパイラが古すぎてこれをサポートできない場合、結果は「(不明)」になります。

51
bk1e

そういうことは何も知らないと言っていたのですが、他の答えを見ました...

実行プロファイラー(gprofなど)がまさに求めていることを実行することを知っていると興味深いかもしれません-各関数の実行に費やされた時間を追跡します。プロファイラーは基本的に、10ms程度ごとに、命令ポインター(IP)、現在実行中の命令のアドレスを記録することによって機能します。プログラムの実行が完了したら、IPのリストとプログラムを調べ、それらのアドレスを関数名に変換するポストプロセッサーを呼び出します。したがって、関数名ではなく命令ポインタを使用することをお勧めします。コーディングが簡単であることと、文字列を使用するよりも単一の数値を使用する方が効率的だからです。

3
David Z