This smells strongly of memory damage. The _vptr is the first pointer-sized object in a
structure, so if you accidentally overwrite the structure, you can clobber it. One of the
easiest ways of clobbering a _vptr is something like
class A {
public:
virtual sometype somefunction(...args...);
A() { ::ZeroMemory(this, sizeof(A)); }
};
because 'this' points to a struct that is really implemented under what you see as if it
were
class A {
really_hidden_by_implementation:
VTABLE * _vptr;
public:
A() { ::ZeroMemory(this, sizeof(A)); }
};
where internally we have also the code
_vptr[0] = somefunction;
set at application startup. The code generated by the compiler for
A->somefunction(...actual args...);
is
(A->_vptr[0])(...actual args...);
but you get all the type checking, overload resolution, etc. [so I've greatly simplified
what is going on). So note that if _vptr is accidentally overwritten, either by the
::ZeroMemory shown here, or by some buffer overrun on the block of memory that just
accidentally precedes the allocation of the instances of class A (whether it is in the
heap or on the stack) you will get the error, even if the A pointer remains valid.
OK, that said, there are some techniques that can be used to detect this.
Probably the simplest one is to download and install the Application Verifier from
Microsoft and configure it to detect memory overruns. Another is to do something reallyl
ugly, such as
typedef struct { FARPROC * vptr; } VPTR_CHECK;
#define CHECK_VPTR(A) ASSERT( ((VPTR_CHECK *)A)->vptr != NULL)
you could sprinkle these around liberally in your code, which requires all sorts of ugly
hacks to get the pointer available. Such a technique could be considred a last resort.
Check all your attempts to write arrays of objects to make sure you aren't clobbering
something important with a buffer overrun. Your damage is almost certainly in that set of
"specific operations" you do when button D is clicked.
joe
On 29 Aug 2006 14:04:38 -0700,
amitdedhia@yahoo.com wrote:
Quote
Hello
I am working on an MDI application. The application's main toolbar
has 4 buttons on it (Lets say A, B, C and D). There is a tab control on
the MainFrame. It has many tabs on it. However, depending on which of
the 4 buttons above has been pressed, only 2 tabs are visible at a
time.
After the application starts, if I click on button C, then I see two
visible tabs. When I click on the right most tab, a window (of type
CMDIChildWnd-derived class) is created. This window has a splitter on
it. It has a data member of type CSplitterWnd.
Everything works fine until I did not click button D.
Once I click button D and do some specific operations and then if I
click on button C - I again see two visible tabs. However, clicking
on rightmost tab thereafter results in an assert. The assert comes
because the __vfPtr member of CSplitterWnd data member is null.
Any idea why this would be happening?
Thanks and regards
Amit Dedhia
Joseph M. Newcomer [MVP]
email:
newcomer@flounder.com
Web:
www.flounder.com">
www.flounder.com
MVP Tips:
www.flounder.com/mvp_tips.htm">
www.flounder.com/mvp_tips.htm
-