0

COM+ アプリケーション、Windows XP SP 3 上の MS Visual Studio 6、SP 6 でビルド、リモートでデバッグ。

私の主な質問はこれです。「削除」に入ることができるのに、「新規」に入ることができないのはなぜですか? 私は主に、何を調べるべきかについてのアイデアを探しています。

私は、慣れてきたばかりのかなり大きなプロジェクトに取り組んでいます。現在の問題は、リリース ビルドが最終的にワーキング セットを使い果たしてクラッシュするヒープ破損の問題です。この問題は非常に広範囲に及ぶため、次のコードでヒープが破損します。

int * iArray = new int [100];
delete [] iArray;

「delete」でデバッグ出力に「ヒープ [dllhost.exe]: rtlvalidateheap に指定された無効なアドレス」が表示されるため、「ヒープを破損する」と言います。

「削除」呼び出しに問題なくステップインでき、適切な呼び出し (...\Microsoft Visual Studio\VC98\CRT\SRC の DELOP.cpp にあります) を呼び出しているようですが、何らかの理由でステップインできません。 「new」への任意の呼び出し。ここでストローをつかんでいますが、コードベースのどこかで誰かが「new」演算子を上書きしたような気がします。私が見ているコードは意図せずにそれを使用しています。リリース ビルドの症状は、メモリが 1 つのヒープに割り当てられ、別のヒープから削除されようとしているように見えます。少なくともそれは私の予感です。

編集:ああ!申し訳ありませんが、投稿が早すぎました。もっと情報を提供する必要がありました。

コード ベースを検索したところ、いくつかのオーバーライドが見つかりましたが、それらはすべてクラス内にあり、グローバルに定義されていません。クラスにない唯一のものは次のとおりです。

struct _new_selector 
{

};

inline void* operator new(size_t, void *ptr, _new_selector)
{
    return (ptr); 
}

しかし、それは新しい配置であり、この状況ではカウントされないと確信しています. 元の「新しい」ために足を踏み入れるべきライブラリは何ですか? 「削除」と同じだと思いますが、そうでない場合は、デバッグ情報がないだけでしょうか?

編集2:これをいじって、デバッグビルドではこの問題が存在しないことがわかりました。ランタイム ライブラリは既に調べましたが、デバッグに /MD と /MDd を使用しています。それだけでなく、確認のために /MDd jut を使用してリリース バージョンをビルドしましたが、それでも変更はありませんでした。デバッグ ビルドとリリース ビルドの両方のマップを見ると、新しい演算子 (マングリングを含む) は次の場所にあります。

リリース:

0001:00061306 ??2@YAPAXI@Z 10062306 f MSVCRTD:MSVCRTD.dll

0002:00000298_imp ??2@ YAPAXI @Z 1006e298 MSVCRTD:MSVCRTD.dll

デバッグ:

0001:00077d06 ??2@YAPAXI@Z 10078d06 f MSVCRTD:MSVCRTD.dll

0004:00000ad4_imp ??2@ YAPAXI @Z 100b5ad4 MSVCRTD:MSVCRTD.dll

私は削除演算子もチェックしました:

リリース:

0001:000611f0 ??3@YAXPAX@Z 100621f0 f msvcprtd:delop_s.obj

デバッグ:

0001:00077bf0 ??3@YAXPAX@Z 10078bf0 f msvcprtd:delop_s.obj

また、私はそれらのプリントアウトを持っていませんが、それが役立つ場合は入手できます。新しいオペレーターの逆アセンブリは、リリースとデバッグで同じように見えます。だから私はそれがオーバーライドではないと思いますか?演算子のインライン オーバーライドはこれを正しくないものにしますか?

また、複数の dllhost.exe プロセスを生成する COM+ アプリケーションであるため、new 演算子の呼び出しが別の DLL または exe に移動し、delete の呼び出しが反対に移動する可能性はありますか?

4

2 に答える 2

3

コードのどこかにオーバーロードされた new がある可能性があるというあなたの予感に従って、チェックできることはほとんどありません

  1. コードを逆アセンブルし、そのファイル内のライブラリ名を見つけます。通常、アセンブリにはヒントを与える何かがあります
  2. ライブラリ名がわからない場合は、入力しているアセンブリ内のアドレスを確認してください。次に、デバッグ出力ウィンドウで、さまざまなライブラリのロード アドレスを確認します。これにより、どのライブラリを確認するかの手がかりが得られます。
  3. 上記で問題が解決しない場合は、プロジェクト全体のマップ ファイルを生成できるかどうかを確認してください。可能であれば、地図ファイルで住所を調べることができ、それが役立つかもしれません
  4. ランタイム ライブラリのデバッグ バージョンを使用してみてください。debug_malloc をオンにするオプションが何であったか思い出せません。これは、ヒープで何が起こっているかを理解するのに役立ちます

コミュニティは、私が見逃した可能性のあるものをさらにいくつか追加できます。最後に、問題を解決した場合は、その方法を共有してください。ここまたはブログへのリンクとして。大規模なプロジェクトのヒープ問題に取り組むのは一般的に簡単ではなく、誰もが新しいトリックを 1 つか 2 つ学ぶことができます。

于 2012-03-07T16:01:14.287 に答える
2

わかりましたので、これが最終的なものです。

私が取り組んでいるプログラムには、約 30 ほどのプロジェクトが含まれています。ライブラリを作成するものもあれば、dll を作成するものもあれば、exe を作成するものもあります。いずれにせよ、すべてが混在しています。これに加えて、ATL と COM を使用すると、すぐにおかしくなり始めます。最終的に、すべてではなく一部のプロジェクトが _ATL_MIN_CRT コンパイラ定義を使用してビルドされました。これはデスクトップ アプリケーションであり、クライアントがいくつかのモジュールをダウンロードする必要がある Web ベースのアプリケーションではありません。

_ATL_MIN_CRT に関する情報を次に示します。

http://support.microsoft.com/default.aspx?scid=kb;EN-US;q166480

http://msdn.microsoft.com/en-us/library/y3s1z4aw%28v=vs.80%29.aspx

最初のリンクから、これによりメモリ割り当てルーチンの使用もなくなることに注意してください。これを使用した最初の動機が何であったのか、それが本当に意図的だったのかはわかりませんが、メモリの割り当てに問題が発生することは確かです. また、これはリリース ビルドにのみ影響するため、見つけるのが大変でした。

基本的に、モジュール A は _ATL_MIN_CRT でビルドされ、モジュール B はそれなしでビルドされましたが、モジュール A に依存していました。これも COM を使用しており、すべてが dllhost.exe で実行されているため、モジュール B が new 演算子を使用しようとすると、ヒープにメモリを割り当てようとするために、DLL から抜け出しました。次に、delete を呼び出すと、その dll 内でそれを削除しようとしました。したがって、クレイジーなメモリリークが発生します。

_ATL_MIN_CRT を削除すると、これは修正されますが、上記で言及したことは、私の理解にすぎません。それは多かれ少なかれ複雑かもしれませんが、それにもかかわらず、これが問題でした.

みんなの提案のおかげで、彼らは私がこのことを見つけるのを本当に助けてくれました!

于 2012-03-20T17:43:50.830 に答える