_DEBUGとNDEBUG


142

コードのデバッグセクションを指定するには、どのプリプロセッサ定義を使用する必要がありますか?

使用する#ifdef _DEBUG#ifndef NDEBUG、それを行うためのより良い方法があり#define MY_DEBUGますか?

_DEBUGVisual Studio固有と思いますが、NDEBUGは標準ですか?

回答:


113

Visual Studioは_DEBUG/MTdor /MDdオプションをいつ指定するかを定義し、NDEBUG標準Cアサーションを無効にします。必要に応じて、つまり_DEBUG、デバッグコードをMS CRTのデバッグ手法NDEBUG一致させたい場合、およびと一致させたい場合に使用しますassert()

独自のデバッグマクロを定義する場合(およびコンパイラーやCランタイムをハックしない場合)、名前をアンダースコアで開始しないでください。これらは予約されているためです。


19
+1。特にNDEBUGは、単一のTU内で#undef'dおよび#define'dすることができます(<assert.h>を再インクルードすると、それに応じてassertマクロが変更されます)。これは期待される/望ましいとは異なるため、この回答にあるように、別のマクロを使用して「コンパイル全体」のデバッグフラグを制御するのが一般的です。

1
どうやら、これらのマクロを定義するのはコンパイラ自体であり、Visual Studio(IDE)ではありません。この回答をどうもありがとう!
Niklas R

Windows Driver Kit 8.1のアプリケーションテンプレートを使用する場合も、NDEBUGは定義されません。この場合、_DEBUGに依存する必要があります。
navossoc

53

NDEBUGは標準ですか?

はい、これはC89、C99、C ++ 98、C ++ 2003、C ++ 2011、C ++ 2014標準のセマンティック「デバッグなし」の標準マクロです。_DEBUG標準にはマクロはありません。

C ++ 2003標準では、「ページ326」の「17.4.2.1ヘッダー」でリーダーを標準Cに送信します。

そのNDEBUGは、これは標準Cライブラリと同じです。

C89(Cプログラマはこの標準を標準Cと呼びました)の「4.2診断」セクションで、

http://port70.net/~nsz/c/c89/c89-draft.html

NDEBUGがソースファイルのインクルードされている場所でマクロ名として定義されている場合、assertマクロは次のように定義されます。

     #define assert(ignore) ((void)0)

_DEBUGVisual Studio https://msdn.microsoft.com/en-us/library/b0084kay.aspxでマクロ の意味を 見ると、このマクロは言語ランタイムライブラリのバージョンの選択によって自動的に定義されていることがわかります。


50

NDEBUGコンパイラーと実装間で動​​作が標準化されているのはだけなので、私はに依存しています(標準のassertマクロのドキュメントを参照)。否定的な論理は小さな読みやすさのスピードバンプですが、すぐに適応できる一般的なイディオムです。

のようなものに依存すること_DEBUGは、特定のコンパイラとライブラリの実装の実装の詳細に依存することです。他のコンパイラーは、同じ規則を選択する場合としない場合があります。

3番目のオプションは、プロジェクトに独自のマクロを定義することです。これは非常に合理的です。独自のマクロを使用すると、実装間での移植性が得られ、アサーションとは無関係にデバッグコードを有効または無効にできます。ただし、一般に、コンパイル時に有効になるデバッグ情報のクラスを変えることはお勧めしません。これは、わずかなメリットのために構築(およびテスト)する必要のある構成の数が増えるためです。

これらのオプションのいずれかを使用して、プロジェクトの一部としてサードパーティのコードを使用する場合は、それが使用する規則に注意する必要があります。


1
#if !defined(NDEBUG)<-@HostileForkはあなたが意図したものではありませんか?#ifじゃない#ifdef
Bob Stein

1
@BobSteinを介して修正された元のコメント:「読みやすさを軽減するために(わずかに)行った「スピードバンプ」の問題は、デバッグなしの状態について話しているときに#ifdef NDEBUG...を使用して否定的なロジックに特別な注意を払うこと#if !defined(NDEBUG)です。それ以外の場合は、中のnをキャッチする少し難しい#ifndef NDEBUG
HostileForkがdont信頼SE言う

17

マクロNDEBUGは、assert()ステートメントがアクティブかどうかを制御します。

私の見解では、これは他のデバッグとは別のものなのでNDEBUG、プログラムのデバッグ情報を制御する以外の方法を使用します。使用するフレームワークは、使用しているフレームワークによって異なります。システムごとに有効化マクロが異なり、私は適切なものを使用しています。

フレームワークがない場合は、先頭にアンダースコアを付けずに名前を使用します。それらは「実装」のために予約される傾向があり、名前の衝突の問題を回避しようとします-名前がマクロの場合は二重になります。


他のタイプのデバッグとは異なるアサートを検討する理由を説明できますか?他のシナリオではなく、どのシナリオが必要ですか?
エイドリアンマッカーシー

4
他のデバッグまたはトレース機能をコードにコンパイルしない場合でも、アサートをアクティブに保ちます。アサーションは不可能な状況を識別します。一般的なトレースとデバッグは、IMOとはまったく別のものです。
ジョナサンレフラー2013

2
@AdrianMcCarthy:すべてのデバッグを有効にすると、プログラムの実行速度が非常に遅くなる可能性があります。そのため、デバッグの種類を分類し、それらを個別に有効化/無効化できるようにするのが一般的です。MSVCには、std :: vectorのような標準ライブラリのさまざまなデバッグを有効または無効にするために使用する2つまたは3つがあります。
Mooing Duck 2013

@MooingDuck:同意しますが、「デバッグ可能および有効」と「デバッグ可能だが無効」および「デバッグ不可」を区別します。使用可能/使用不可の決定は、コンパイル時の問題(CまたはC ++コードの場合)であり、デバッグが使用可能になると、使用可能/使用不可がランタイムの決定になります。最も粗末なデバッグシステムのみが、「利用可能な手段を有効にする」モードで動作します。(とはいえ、原油は効果的であり、途方もない原油がたくさんありますが、十分に効果的ですが、実際にシステムをデバッグしています!)
Jonathan Leffler

2
@MooingDuck:はい、一部のデバッグコードは動作が遅くなる可能性があります。その場合、遅いコードが簡単なチェックとは独立して実行されるかどうかを制御する方法必要になる場合があります。しかし、これはアサーションを1つのカテゴリに入れ、#if制御されたコードを他のカテゴリに入れることと同じではありません。 おそらくそうではないassert(huge_object.IsValid());かもしれませんが、遅いかもしれませassert(ptr != nullptr);ん。ロギングトレースは、少なくとも大規模なプロジェクトではおそらくアサーションとは区別されるべきだとジョナサンに同意しますが、ログトレースをデバッグコードとして考えていません。
Adrian McCarthy

6

一貫性があり、どちらでもかまいません。また、何らかの理由で特定のデバッグ識別子を使用して別のプログラムまたはツールと相互運用する必要がある場合も、簡単に実行できます

#ifdef THEIRDEBUG
#define MYDEBUG
#endif //and vice-versa

4

残念ながらDEBUG、負荷が非常に高くなっています。たとえば、RELEASEビルド用のpdbファイルを常に生成して保存することをお勧めします。つまり、-Zxフラグの1つと-DEBUGリンカーオプションです。While _DEBUGは、mallocやへの呼び出しなど、ランタイムライブラリの特別なデバッグバージョンに関連していますfree。その後、NDEBUGアサーションを無効にします。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.