printf
スタイルのデバッグでは、人々は常にプリプロセッサマクロを使用しているようです。これに似たソリューションに何か問題がありますか?
void debug(char *msg) {
#ifdef DEBUG
printf("%s", msg);
#endif
}
通常、彼らがこのようなことをすることができるように:
#define DEBUG(MSG) printf("[%s:%i] %s\n", __FILE__, __LINE__, (MSG))
デバッグメッセージの正確なソースをログに記録しておくと非常に便利なので、これはかなり一般的なパターンです。しかし、次のような関数を使用した場合:
void DEBUG(const char *MSG) {
printf("[%s:%i] %s\n", __FILE__, __LINE__, (MSG));
}
そうすると、のprintf()
呼び出しに対応するファイル名と行番号のみが表示され、を呼び出しDEBUG()
たコードのファイル名と行番号は表示されませんDEBUG()
。
msg
1)printfはフォーマット文字列を想定しているため、 is%d
などの 場合はコードが壊れます。printf("%s", msg);
優れている。
2)そうではありません。マイクロ最適化(コードサイズなど)を行っていない限り、マクロは多用されています。stop in debug
関数は、デバッガーのようなことを実行できるため、デバッグが容易です。マクロには注意が必要なものが他にも無数にあります。http://www.brainbell.com/tutors/c/Advice_and_Warnings_for_C/Macros_and_Miscellaneous_Pitfalls.htmlを参照してください
3)@Jonathan Grynspanが指摘したように、マクロ形式はFILE、LINEで使用する方が簡単です。私の意見では、開発者はタイピングのショートカットを使用して、後で他の人のためにコードを維持するのを難しくし、皮肉なことに後で自分自身をデバッグするのを難しくします。ベストプラクティスIMO:extraと入力し、コードをデバッグしやすく、デバッガーで実行しやすくし、署名付きの関数を使用しますdebug(const char* msg, const char* FILE_LOC, unsigned LINE_NUMBER)
マクロを使用する場合DEBUG
、単一の#defineステートメントまたはコンパイルオプションを変更して再コンパイルすると、すべてのデバッグコードが実行可能ファイルから消える可能性があります。対照的に、DEBUG()
関数を使用する場合、関数自体が何かを実行するかどうかに関係なく、すべての呼び出しで関数を呼び出すコードが生成されます。
__FILE__
、の使用だけでなく__LINE__
、以下も比較する必要があります。
#ifdef NDEBUG
#define DEBUG_PRINT(...) ((void)0)
#else
#define DEBUG_PRINT(...) printf(__VA_ARGS__)
#endif
あなたの機能に対して:
void debug(const char* msg) {
#ifndef NDEBUG
printf("%s", msg);
#endif
}
マクロを使用すると、次のように書くことができます。
DEBUG_PRINT("Expected %d, got %d\n", correct_value, result);
この関数を使用すると、整数を使用して1つ以上の文字列を作成し、関数を1回以上呼び出す必要があります。リリースモードでは、関数は何も実行しないため、文字列は使用されません。オプティマイザーは、それを構築するためのコードをなんとか排除するかもしれませんし、そうでないかもしれません。マクロがあれば間違いありません。
debug
そうは言っても、varargsを使って正しいことをする関数を書くことができます。ただし、記述された関数は最終的にこの問題にぶつかるので、を追加する必要がありますdebugf
。