不可解なクラッシュがあり、これまでのところ、一貫して再現することは不可能であることがわかりました。コードは Visual Studio 2008 でコンパイルされています。
(もちろん簡略化された) ソースコードは次のようになります。
class AbstractParentClass
{
private:
/* data members */
public:
AbstractParentClass();
/*
virtual functions ...
*/
};
class ChildClass : public AbstractParentClass
{
private:
/* data members */
public:
ChildClass();
/*
overridden/implemented virtual functions ...
*/
};
void DifferentClass::func(const char ** strs)
{
ChildClass child_class;
int i = 0;
[...]
}
クラッシュ ダンプからの逆アセンブルは次のようになります。
Library!DifferentClass::func:
612cab20 83ec58 sub esp,58h
612cab23 56 push esi
612cab24 57 push edi
612cab25 8bf9 mov edi,ecx
612cab27 8d4c2420 lea ecx,[esp+20h]
612cab2b e8e053403f call a06cff10
612cab30 8b742464 mov esi,dword ptr [esp+64h]
[...]
逆アセンブリに対して func() のソースをマッピングすると、次のようになります。
Library!DifferentClass::func:
void DifferentClass::func(const char ** strs)
{
612cab20 83ec58 sub esp,58h
612cab23 56 push esi
612cab24 57 push edi
612cab25 8bf9 mov edi,ecx
ChildClass child_class;
612cab27 8d4c2420 lea ecx,[esp+20h]
612cab2b e8e053403f call a06cff10
int i = 0;
612cab30 8b742464 mov esi,dword ptr [esp+64h]
[...]
}
正常に実行された場合 (別のマシン、同じマシンでも、クラッシュは確実に再現できません)、逆アセンブリの唯一の違いは call 命令です。これ:
00404e8b call ChildClass::ChildClass (40a3d0h)
好きではなく:
612cab2b call a06cff10
そのため、クラッシュ実行では、呼び出し命令のパラメーターとして機能する a06cff10 アドレスは、誰がどこから来たのかを知っているようで、特に何にもマップされていません。そのため、予想どおり、そのアドレスに (ChildClass の既定のコンストラクターに到達するために) アクセスしようとすると、アクセス違反が発生します。
EXCEPTION_RECORD: 0012f688 -- (.exr 0x12f688)
ExceptionAddress: a06cff10
ExceptionCode: c0000005 (Access violation)
ExceptionFlags: 00000000
NumberParameters: 2
Parameter[0]: 00000000
Parameter[1]: a06cff10
Attempt to read from address a06cff10
クラッシュ ダンプでそのアドレスを調べようとすると、アドレスがプロセスの範囲外にあることが示されます。
更新: 以下の zvrba からの応答を読んでさらに詳しく調べたところ、問題のある呼び出しは、静的ライブラリ (DLL によって読み込まれる) 内の 12 ほどの関数呼び出しの最初の呼び出しであると思われます。関数オフセット。それらはすべて同じクラスの関数ではありません。すべてのクラス (呼び出し元と呼び出し先の両方) が同じ静的ライブラリに存在しますが、関数が影響を受ける 3 つまたは 4 つの異なるクラスがあります。クラッシュしたこの最初の呼び出しでは、命令は e8e053403f であり、その命令の 3F4053E0 オフセットはちょうど 53E0 のオフセットでした。他のすべてのインスタンスには、同じオフセットの問題があります。命令のオフセットは 3F40XXXX ですが、XXXX だけである必要があります。余分な 3F400000 はもちろん、ネバー ネバー ランドに物を送り込んでいます。これまでのところ、逆アセンブリ内のどの関数アドレスが有効で、どれが有効かどうかに関するパターンを見つけていません。ライブラリ内の DifferentClass の 1 つのメンバー関数では、ChildClass へのすべての呼び出しが不適切であると見なされますが、別のメンバー関数 DifferentClass では、ChildClass への別の呼び出しが適切に表示されます。
誰かがこのようなものを見たことがありますか/その考えられる原因について何か考えがありますか?