I have a crash that's puzzling me and that I thus far have found impossible to consistently reproduce. The code is compiled with Visual Studio 2008.
The (simplified, of course) source code looks like this:
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;
[...]
}
The disassembly from the crash dump looks like this:
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]
[...]
Mapping the source of func() against the disassembly, it winds up looking like this:
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]
[...]
}
In a successful run (different machine, though even on the same machine, the crash is not reliably reproducible), the only difference in the disassembly is the call instruction, which winds up mapping correctly to the address of the default constructor of ChildClass, like this:
00404e8b call ChildClass::ChildClass (40a3d0h)
rather than like:
612cab2b call a06cff10
So in the crash run, that a06cff10 address that serves as the call instruction's parameter seems to be coming from who-knows-where and is not mapped to anything in particular. And so, predictably, trying access that address (to get to the ChildClass default constructor) is resulting in an access violation:
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
Any attempt to look at that address in the crash dump indeed indicates that the address is out of bounds for the process.
UPDATE: So after reading the response below from zvrba and looking further at it, the problematic call seems to be the first of a dozen or so function calls within a static library (that is in turn loaded by a DLL) that all have an incorrect function offset. They're not all functions in the same class. There are three or four different classes with functions affected, though all the classes (both invoking and being invoked) live in that same static library. In this first call which crashed things, the instruction was e8e053403f and the 3F4053E0 offset in that instruction should have been an offset of just 53E0. All of the other instances have the same offset problem. The offset in the instruction is 3F40XXXX, when it should be just XXXX. The extra 3F400000 is of course sending things off into Never Never Land. So far, I haven't picked up on an pattern with regard to which function addresses within the disassembly are valid and which or not. One member function of DifferentClass in the library will have all of its calls to ChildClass as bad, whereas another member function DifferentClass will have a different call into ChildClass look just fine.
Has anyone out there seen something like this/have any thoughts on likely causes thereof?