0

SQLite ファイルをファイル形式として使用する Windows フォーム アプリケーションがあります。ファイルは、C++/CLI ラッパー経由で呼び出されるネイティブ コードによって作成されます。このラッパーには、進行状況/キャンセルの更新のためのマネージ コードへのコールバックが含まれています。これは、32ビットでうまく機能しています。64 ビットに切り替えてメモリの上限を取り除こうとしていますが、大きな問題が発生しました。

ネイティブ コード内でメモリが割り当てられているか、割り当てが解除されているときに疑似決定論的クラッシュが発生し、メモリの破損が考えられます。ただし、これはリリース ビルド中にのみ発生し、デバッガーが接続されていない場合にのみ発生します。これが私の悪夢の内訳です:

Config Bits Optimizations Interop Dbg-symbols Runtime With-debugger Without-debugger
リリース 32 on no no /MD no crash no crash
yes no /MD no crash no crash でリリース 64
yes no /MD no crash no crash でリリース 32
yes no /MD no crash で 64 をリリース
yes yes /MD no crash でリリース 64 クラッシュ
リリース 64 オフ はい いいえ /MD いいえ クラッシュ いいえ クラッシュ
リリース 64 オフ はい はい /MD いいえ クラッシュ いいえ クラッシュ
デバッグ 32 オフ いいえ はい /MDd いいえ クラッシュ いいえ クラッシュ
デバッグ 32 オフ はい はい /MDd いいえ クラッシュ いいえ クラッシュ
デバッグ 64 オフ はい はい /MDd いいえ クラッシュ いいえ クラッシュ
はい はい /MD で 64 をデバッグする いいえ クラッシュ いいえ クラッシュ
yes no /MD で 64 をデバッグ no crash no crash
デバッグ 64 オフ はい はい /MD いいえ クラッシュ いいえ クラッシュ
デバッグ 64 オフ はい はい /MDd いいえ クラッシュ いいえ クラッシュ
はい はい /MDd で 64 をデバッグする いいえ クラッシュ いいえ クラッシュ
yes no /MD で 64 をデバッグ no crash no crash

「相互運用」とは、GUI アプリケーションから C++/CLI ラッパーを使用してネイティブ パーサー コードを実行していることを意味します。ネイティブ C++ で記述され、どの構成でもクラッシュしないコマンドライン ドライバーがあります。

基本的に、ネイティブコードがリリースコードとまったく同じようにコンパイルされている場合でも、デバッグ構成がクラッシュすることはありません! 応答ファイルを比較しましたが、デバッグ構成用に _NO_DEBUG_HEAP=1 を追加した以外は同じです。/MD を使用して NDEBUG を定義する場合、とにかく影響があるとは思えません。では、この悪夢をどのようにデバッグすればよいでしょうか? 私のコードに問題があるようには感じません。小さな再現を求めないでください。作り方がわかりません。しかし、コードはすべてオープン ソースなので、誰かがこれを再現しようとする場合は、ソースへのリンクを投稿します。

4

1 に答える 1

0

Heisenbug は通常、メモリ ストンプ (マネージ コードでは発生しません) またはメモリ内のゴミを有効なデータとして処理することによって発生します。

私は、初期化されていない変数を使用して別のルーチンからスタックにあったものを取得することになった、一般的に再現可能なハイゼンバグを複数探しました。ネイティブ コードには、ある値を取得すると機能し、別の値を取得すると爆発するようなバグが含まれている可能性があります。デバッグとリリースは、舞台裏のものが同じであることを保証するものではなく (結局のところ、なぜ 2 つの構成があるのでしょうか?)、メモリ内に異なるゴミが存在する可能性があります。

オプティマイザーもそのような影響を与える可能性があります。

私が試してみたいことの 1 つは、ネイティブ コードの最初のルーチンのローカル変数に実質的な構造を平手打ちすることです。リンカーがそれを取り除かないようにするために何かをしてください。

これにより、動作が変わるはずです。

于 2012-06-13T22:48:19.527 に答える