大規模なシステムでクラッシュするコードがあります。ただし、コードは基本的に次の擬似コードに要約されます。これを最小限の骨にまで煮詰めようとしたので、詳細の多くを削除しました。私はこれが決定的なものを見逃すとは思わない。
// in a DLL:
#ifdef _DLL
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP __declspec(dllimport)
#endif
class DLLEXP MyClass // base class; virtual
{
public:
MyClass() {};
virtual ~MyClass() {};
some_method () = 0; // pure virtual
// no member data
};
class DLLEXP MyClassImp : public MyClass
{
public:
MyClassImp( some_parameters )
{
// some assignments...
}
virtual ~MyClassImp() {};
private:
// some member data...
};
と:
// in the EXE:
MyClassImp* myObj = new MyClassImp ( some_arguments ); // scalar new
// ... and literally next (as part of my cutting-down)...
delete myObj; // scalar delete
一致するスカラー new とスカラー delete が使用されていることに注意してください。
Visual Studio (2008 Pro) のデバッグ ビルドでは、Microsoft の <dbgheap.c> で次のアサーションが失敗します。
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
スタックの一番上には、次のアイテムがあります。
mydll_d.dll!operator delete()
mydll_d.dll!MyClassImp::`vector deleting destructor'()
こうあるべきだと思う
mydll_d.dll!MyClassImp::`scalar deleting destructor'()
つまり、プログラムは私が書いたかのように動作しています
MyClassImp* myObj = new MyClassImp ( some_arguments );
delete[] newObj; // array delete
のアドレスpUserData
は、myObj
(メンバーではなく) それ自体のアドレスです。そのアドレス周辺のメモリは次のようになります。
... FD FD FD FD
(address here)
VV VV VV VV MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE
...
ここで、4 つVV
の s はおそらく仮想関数テーブルのアドレスであり、MM...MM
認識可能なメンバー データであり、他のバイトはデバッガーによって配置されたさまざまな特別なマーカーです (たとえば、FD FD
s はオブジェクトのストレージの周りの「ガード バイト」です)。
アサーションが失敗する少し前に、VV
s が変更されているのを確認しました。これは、基本クラスの仮想関数テーブルへの切り替えによるものではないかと考えています。
クラス階層の間違ったレベルが破壊されるという問題を認識しています。それはここでは問題ではありません。私のデストラクタはすべて仮想です。
Microsoft のページ "BUG: エクスポートされたクラスに対して間違った演算子の削除が呼び出されました" http://support.microsoft.com/kb/122675に注意 してください。データ。
私の場合、デストラクタを削除するという間違った「フレーバー」が適用されているようです。つまり、スカラーではなくベクトルです。
私は、まだ問題が発生する最小限のカットダウン コードを作成しようとしています。
ただし、この問題をさらに調査する方法に役立つヒントやヒントをいただければ幸いです。
おそらく、ここでの最大の手がかりmydll_d.dll!operator delete()
はスタックにあります。s が「失われた」myexe_d.exe!operator delete()
ことを示す であると期待する必要がありますか?DLLEXP
これは二重削除のインスタンスである可能性があると思います(しかし、そうは思いません)。
_CrtIsValidHeapPointer
何をチェックするかに関して私が読むことができる良い参考文献はありますか?