醜いMFC ASSERTマクロを何年も使用した後、私はようやくそれを捨てて、究極のASSERTマクロを作成することにしました。
ファイルと行番号、さらには失敗した式を取得しても問題ありません。これらが入ったメッセージボックスと、中止/再試行/キャンセルボタンを表示できます。
そして、[再試行]を押すと、VSデバッガーはASSERT呼び出しを含む行にジャンプします(逆アセンブルが他のASSERT関数のような場所にあるのとは対照的です)。ですから、ほとんど問題なく動いています。
しかし、本当にクールなのは、失敗した関数の名前を表示することです。
次に、ファイル名からどの関数が含まれているかを推測することなく、デバッグするかどうかを決定できます。
例えば次の機能がある場合:
int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
ASSERT(lpCreateStruct->cx > 0);
...
}
次に、ASSERTが起動すると、メッセージボックスは次のように表示されます。
Function = CMainFrame::OnCreate
つまり、実行時に現在の関数名を見つける最も簡単な方法は何ですか?
MFCも.NET Frameworkも使用しないでください。両方を使用しています。
可能な限り移植可能である必要があります。
マクロには__FUNCTION__
マクロを含めることができます。間違いなく、関数名されるは拡張コードにコンパイル時に挿入されますが、マクロへの呼び出しごとに正しい関数名になります。したがって、実行時に発生するように見えます;)
例えば.
#define THROW_IF(val) if (val) throw "error in " __FUNCTION__
int foo()
{
int a = 0;
THROW_IF(a > 0); // will throw "error in foo()"
}
C++プリプロセッサマクロ__FUNCTION__
は、関数の名前を示します。
これを使用すると、実行時にファイル名、行番号、または関数名を取得するreallyではないことに注意してください。マクロはプリプロセッサによって展開され、コンパイルされます。
__FUNCTION__
マクロは、__LINE__
や__FILE__
と同様に、言語標準の一部であり、移植可能です。
プログラム例:
#include <iostream>
#using namespace std;
void function1()
{
cout << "my function name is: " << __FUNCTION__ << "\n";
}
int main()
{
cout << "my function name is: " << __FUNCTION__ << "\n";
function1();
return 0;
}
出力:
私の関数名は:main 私の関数名は:function1
標準的な解決策はありません。しかしながら、 - BOOST_CURRENT_FUNCTION
は、あらゆる実用的な目的で移植可能です。ヘッダーは他のBoostヘッダーに依存しないため、ライブラリ全体のオーバーヘッドが許容できない場合はスタンドアロンで使用できます。
__FUNCTION__
または__FUNC__
または__PRETTY_FUNCTION__
http://msdn.Microsoft.com/en-us/library/b0084kay(VS.80).aspxhttp://gcc.gnu.org/onlinedocs/gcc/Function -Names.html
GCCでは、__PRETTY_FUNCTION__
マクロを使用できます。
Microsoftには同等の__func__
マクロもありますが、試すことはできません。
例えば__PRETTY_FUNCTION__
を使用するには、関数の先頭にこのようなものを配置すると、完全なトレースが得られます
void foo(char* bar){
cout << __PRETTY_FUNCTION__ << std::endl
}
出力されます
void foo(char* bar)
さらに多くの情報を出力したい場合は、__FILE__
および__LINE__
マクロをすべての標準c/c ++コンパイラーで使用できます。
実際には、coutの代わりに使用する特別なデバッグクラスがあります。適切な環境変数を定義することで、完全なプログラムトレースを取得できます。同様のことができます。これらのマクロは非常に便利であり、このような選択的なデバッグをフィールドでオンにできることは本当に素晴らしいことです。
編集:明らかに__func__
は標準の一部ですか?知らなかった。残念ながら、これは関数名のみを提供し、パラメーターも提供しません。私はgccの__PRETTY_FUNC__
が好きですが、他のコンパイラに移植することはできません。
GCCは__FUNCTION__
もサポートしています。
__FUNCTION__
マクロ コンパイル時に関数の名前に展開されます。
これは、assertマクロで使用する方法の例です。
#define ASSERT(cond) \
do { if (!(cond)) \
MessageBoxFunction("Failed: %s in Function %s", #cond, __FUNCTION__);\
} while(0)
void MessageBoxFunction(const char* const msg, ...)
{
char szAssertMsg[2048];
// format args
va_list vargs;
va_start(vargs, msg);
vsprintf(szAssertMsg, msg, vargs);
va_end(vargs);
::MessageBoxA(NULL, szAssertMsg, "Failed Assertion", MB_ICONERROR | MB_OK);
}
funcを簡単に使用できます。実行時に例外を発生させた現在の関数名を取り戻します。
使用法:
cout << __func__ << ": " << e.what();