2009-04-09 12 views
23

関数トレーサを実装して、関数の実行にどれくらいの時間がかかるかを調べたいと思います。私は、関数の内部から関数の名前を取得する方法があるかどうかを知りたい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. 
    */ 
} 

- :私は同じのために以下のクラスがありますか?基本的には、私のクラスのユーザーが同じオブジェクトを単純に作成したいと思っています。関数名を渡すことはできません。

答えて

21

VC++は

__FUNCTION__ for undecorated names 

__FUNCDNAME__ for decorated names 

を持っているそして、あなたは、それ自体がオブジェクトを割り当て、コンストラクタの内部名-yeldingマクロを渡すマクロを書くことができます。

#define ALLOC_LOGGER FuncTracer ____tracer(__FUNCTION__); 
+0

VS2003で動作しますが、VC6で動作しません。 – Canopus

+0

何が問題なのですか?マクロはコンパイラによって認識されません、または何ですか? – sharptooth

+0

はい。 VC6のコンパイルでは、宣言されていない識別子として__FUNCTION__と表示されます。私は何かを逃しているのですか、それともサポートされていませ – Canopus

46

C99は__func__を持っていますが、C++、これは特定のコンパイラとなりますためのようになめらか。プラスの面では、コンパイラ固有のバージョンのいくつかが追加の型情報を提供します。これは、テンプレート化された関数/クラスの内部をトレースするときに特に便利です。

  • MSVC__FUNCTION____FUNCDNAME____FUNCSIG__
  • GCC__func____FUNCTION____PRETTY_FUNCTION__

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

3

私は...私はどのような事を知りませんでしたが、その後、私は他の回答を見たと言って

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

+1

これを実行するには、実行可能ファイル/ライブラリのイメージ読み込みアドレスも保存する必要があります。そうしないと、記録されたアドレスを意味のあるものと解釈できない場合があります。また、カスタムプロファイラ(MSVCの_penter/_pexitなど)に対するコンパイラのサポートは、定期的なサンプリングの代わりになる可能性があります。 – bk1e

関連する問題