リリース バージョンのバグがデバッグ モードに存在しない一般的な理由

StackOverflow https://stackoverflow.com/questions/1762088

  •  21-09-2019
  •  | 
  •  

質問

リリース コンパイル モードでのみ現れ、デバッグ モードでは発生しないバグや異常なプログラム動作の一般的な理由は何ですか?

役に立ちましたか?

解決

明示的に述べない限り、同じリリースモードでは発生しないのに対し、Cでのデバッグモードで何回も、++すべての変数がnull、初期化されます。

すべてのデバッグマクロと初期化されていない変数を確認してください。

、その後、最適化はまた、リリースモードでいくつかの問題を引き起こす可能性があります。

あなたのプログラムがスレッドを使用しています。

また例えば、すべての例外をチェックしませ直接VC ++でのMEMアクセス違反と同様に、モードを解除するが、いつか私たちはいくつかの重要な例外を無視するように関連するが、同じでは、Linux、Solarisのような他のOSで、少なくとも問題になることができます。理想的には、あなたのプログラムは、NULLポインタにアクセスするように、このような重要な例外をキャッチするべきではありません。

他のヒント

一般的な落とし穴は、ASSERT内部副作用を持つ式を使用しています。

その他の違いは次のとおりです。

  • ゴミ収集言語では、コレクターは通常、リリースモードでより攻撃的です。
  • メモリのレイアウトはしばしば異なる場合があります。
  • メモリの初期化が異なる場合があります(例えば、デバッグモードではゼロになったり、リリースでより積極的に再利用される可能性があります)。
  • 地元の人々は、リリース中の登録値に昇進する可能性があり、これにより、浮動小数点値の問題が発生する可能性があります。

私は過去に、デバッグ ビルドでは問題なかったものの、リリース ビルドではクラッシュする多くのバグに遭遇しました。根本的な原因は数多くあります (もちろん、このスレッドですでにまとめられているものも含まれます) が、私は次のすべてに該当しました。

  • のメンバー変数またはメンバー関数 #ifdef _DEBUG, そのため、デバッグ ビルドではクラスのサイズが異なります。時々 #ifndef NDEBUG リリースビルドで使用されます
  • 同様に、別のものもあります #ifdef これはたまたま 2 つのビルドのうちの 1 つにのみ存在します
  • デバッグ バージョンでは、システム ライブラリ、特にヒープおよびメモリ割り当て関数のデバッグ バージョンを使用します。
  • リリースビルドのインライン関数
  • ヘッダー ファイルを含める順序。これで問題が発生することはありませんが、次のような問題がある場合は、 #pragma pack リセットされていない場合、厄介な問題が発生する可能性があります。同様の問題は、プリコンパイルされたヘッダーと強制インクルードを使用しても発生する可能性があります。
  • キャッシュ:リリース ビルドでのみ使用されるキャッシュや、異なるキャッシュ サイズ制限などのコードがある可能性があります。
  • プロジェクト構成:デバッグ構成とリリース構成には異なるビルド設定が含まれる場合があります (これは、IDE を使用する場合に発生する可能性があります)
  • デバッグのみのコードの結果として発生する競合状態、タイミングの問題、その他の副作用

デバッグ/リリースのバグを解明するために私が長年にわたって蓄積してきたいくつかのヒント:

  • 可能であれば、デバッグ ビルドで異常な動作を再現してみてください。それを捕捉する単体テストを作成するとさらに良いでしょう。
  • この 2 つの違いについて考えてみましょう。コンパイラ設定、キャッシュ、デバッグ専用コード。それらの違いを一時的に最小限に抑えるようにしてください
  • 最適化をオフにしてリリース ビルドを作成するか (デバッガーで有用なデータを取得できる可能性が高くなります)、または最適化されたデバッグ ビルドを作成します。デバッグとリリースの間の変更を最小限に抑えることで、どの違いがバグの原因となっているかを特定できる可能性が高くなります。

はい!、あなたは条件付きコンパイルを持っている場合は、バグ(最適化されたリリースコードの詩、非最適化デバッグコード)、デバッグヒープ対メモリーの再利用のタイミングがあるかもしれません。

これはあなたがCレルムにある場合は特に、することができます。

一つの原因は、デバッグバージョンが浮遊ポインタのチェックと何とかクラッシュ(または正しく動作)からあなたのコードを保護するためのコードを追加することができているかもしれません。この場合は、あなたが慎重にあなたのコンパイラから取得警告やその他のメッセージを確認する必要があります。

もう一つの原因は、(リリースバージョンとデバッグのためのオフのために通常である)の最適化である可能性があります。コードとデータのレイアウトが最適化されている可能性があり、あなたのデバッグプログラムは、ちょうどリリースバージョンは、現在予約メモリにアクセスしようとしたり、コードを指している、未使用のメモリへのアクセス、例えば、あった!

編集:もちろん、あなたは、デバッグモードでコンパイルしていない場合は、条件付きで除外されている全体のコードセクションがある可能性があります:私は他がそれを言及した参照してください。そのような場合、私はそれが本当にプログラム自体の正しさのために不可欠なコードではなく、何かをデバッグしている願っています!

CRTライブラリ関数がリリース対デバッグで異なる動作を(/ MD対/ MDD)。

たとえば、デバッグバージョンは、多くの場合、あなたはあなたの主張を検証するために指示された長さに渡すバッファを事前入力します。例としては、より良いのことがあなたののszDest の、文字列は早く終了した場合でもstrcpy_sStringCchCopy、などが含まれるn個は長いバイト!

確かに、例えば、あなたが

のような構造を使用している場合
#if DEBUG

//some code

#endif
それは同様にのみバグを解放するために導くことができ、デバッグモードであるよりも、あなたは#if DEBUGなどの条件付きコンパイルを使用しない場合でも、.NETでは、コンパイラがまだたくさんより自由リリースモードでの最適化です。

あなたは多くの、より多くの情報を提供する必要があると思いますが、はい、それは可能です。それはあなたのデバッグバージョンが何をするかによって決まります。あなたもロギングやリリースバージョンにコンパイルされません。その内の余分なチェックを有することができます。これらのデバッグのみのコードパスは状態を変更したり、奇妙な方法で変数に影響を与える意図せぬ副作用を有することができます。デバッグは、通常は実行速度が遅く構築し、これはスレッドに影響を与えると競合状態を隠すことがあります。 (そう、これらの日が)リリースコンパイルからまっすぐ進むの最適化のために同じことが、それは可能です、そのリリースのコンパイルかもしれ短絡最適化などの何かます。

の詳細がなければ、私は「OKではない」と仮定します、それは、コンパイルや実行時に何らかのエラーをスローしないかということを意味します。あなたは#if DEBUG文を介して、またはConditional属性でマークする方法のいずれかを介して、コンパイルのバージョンに依存しているコードを持っているかどうか確認します。

それはあなたが条件付きコンパイルを持っている場合は、デバッグコードするように、可能であり、コードをリリース異なり、リリースモードでのみ使用されるコードにバグがあります。

それ以外は、それは不可能です。そこデバッグコードと解除コードがコンパイルされているかの違いがあり、デバッガの下で実行するかどうコードが実行される方法の違いは、しかし、それらの違いのいずれかがパフォーマンスの違い以外が発生した場合、問題がすべてに沿っていました。

(タイミングやメモリの割り当てが異なるため)

デバッグバージョンでエラーがoccuringされないことがあり、それはエラーがないことを意味するものではありません。あり、エラーが発生する原因となるかどうか、コードのタイミングを変更し、デバッグモードに関連しない他の要素であってもよいが、それはすべてのコードが正しかった場合、エラーが発生しないという事実に帰着しますいずれかの状況インチ

だから、いや、デバッグバージョンを使用すると、エラーを取得せずに、それを実行することができますという理由だけでOKではありません。あなたはリリースモードでそれを実行すると、エラーが発生した場合、それはエラーが最初からあったので、それはだ、ではないので、リリースモードのです。

彼らはあまりにも積極的であるため、

のコンパイラの最適化がありますが、有効なコードのを破ることができます。

オン少ない最適化を使用してコードをコンパイルしてみます。

void以外の関数では、すべての実行パスは、return文で終了する必要があります。

デバッグモードでは、あなたがreturn文で、このようなパスを終了するのを忘れた場合、関数は通常、デフォルトでは0を返します。

ただし、リリースモードであなたの関数は、プログラムが実行される方法に影響を与える可能性がある、ごみ値を返すことがあります。

それは可能です。それが起こると何の条件付きコンパイルは、あなたのプログラムが間違っていることをかなり確信することができるよりも、関与していない、とだけのため偶然のメモリ初期化のまたはメモリ内にもレイアウト!

デバッグモードで動作している場合

私は、レジスタ以前の値を回復していなかったアセンブリ関数を呼び出したとき、私はちょうどことを経験しました。

「リリース」の構成では、VSはスピードのためにコードを最適化/ O2でコンパイルされました。単に重大なメモリの破損につながる前述の機能と共有された(最適化)CPUレジスタにマッピングしたがって、いくつかのローカル変数

とにかくあなたは間接的にあなたのコード内の任意の場所にCPUのレジスタをいじっていないかどうかを確認します。

少し前に、C/C++ で DLL と PDB を構築していたときのことを思い出します。

私はこれを覚えています:

  • ログ データを追加すると、バグが移動したり消えたり、まったく別のエラーが表示されたりすることがあります (したがって、実際にはオプションではありませんでした)。
  • これらのエラーの多くは、strcpy や strcat での char の割り当てや char[] の配列などが原因です。
  • Bounds Checkerを実行し、メモリAlloc/Deallocの問題を単に修正することで、いくつかを除去しました。
  • 何度も、体系的にコードを調べて、文字の割り当てを修正しました (すべてのファイルを調べるなど)。
  • それは間違いなく、メモリの割り当てと管理、およびデバッグ モードとリリース モードの制約と違いに関連したものです。

そして、最善の結果を期待しました。

これらのバグに対処している間、本番を延期しないように、一時的に DLL のデバッグ バージョンをクライアントに配信することがありました。

もう一つの理由は、DBの呼び出しである可能性があります。 あなたは、同じスレッドで複数回保存し、同じレコードを更新しています、 時々更新のため。 その可能更新が失敗したかdidntの仕事は予想通り、以前作成したコマンドがまだ処理されたため、更新のために、デシベルコールは任意のレコードを見つけることができませんでした。 デバッガが着陸する前に、すべての保留中のタスクを完了することを確認しますので、これは文句を言わないデバッグに起こります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top