14

I am debugging a defect and have narrowed it down to the vtable pointer for an object being 0xdddddddd. This answer indicates that Win32 debug builds will generally set dead memory, or memory which has been deleted, to this special value.

Note that the pointer itself looks valid, it's just the vtable pointer that is 0xdddddddd.

Here's a snippet of code:

std::list<IMyObject*>::const_iterator it;
for (it = myObjects.begin(); it != myObjects.end(); ++it)
{
    IMyObject* pMyObject = *it;
    if (pMyObject == 0)
        continue;

    pMyObject->someMethod(); // Access violation     
}

If I break at the line of the access violation and watch pMyObject, I can see that pMyObject itself has a valid address (0x08ede388) but the __vfptr member is invalid (0xdddddddd).

Some notes:

  • It's a single-threaded application, so this is most likely not a race condition or mutex issue.
  • There don't appear to be any obvious issues like deleting the object further up the call stack before accessing it.
  • This issue seems to only be reproducible on Windows 2008 server, but not on Windows 7.

Any suggestions about how to debug this further?

Community
  • 1
  • 1
LeopardSkinPillBoxHat
  • 28,915
  • 15
  • 75
  • 111
  • This looks like a classic case of somebody deleting the object after putting the pointer into the list. Are you sure that is not the case (it might be deleted from some other function after filling the list, so taking a look at the call stack may not be of much help). The simplest thing to try is to put a breakpoint in the destructor of `IMyObject` and see somebody is deleting the object. – Naveen Apr 19 '11 at 07:44

4 Answers4

13

You are using the pointer after it has been released. Get a stack trace from a breakpoint in the destructor to see what is deleting it. Or better yet, use shared_ptr<> to avoid the problem.

janm
  • 17,976
  • 1
  • 43
  • 61
  • Thanks, these objects are created/destroyed 1000s of times, so this could be difficult (not even sure a conditional breakpoint will help because i'm not sure what the condition would be). But I'll start investigating. – LeopardSkinPillBoxHat Apr 19 '11 at 07:46
  • 2
    You are looking for a case where the object is deleted without the pointer being removed from the list, or a case where an object could be inserted into the list more than once, but only removed from the list once on deletion. – janm Apr 19 '11 at 07:49
  • @LeopardSkinPillBoxHat: ... or a case where the object is added into the list and then deleted outside of the list. The simple approach is avoiding raw pointers and storing one of the available smart pointers (`QSharedPointer` could be a good candidate). – David Rodríguez - dribeas Apr 19 '11 at 07:59
2

Okay wow, so I've been programming in c++ for years and never discovered this until now... There are actually magic numbers/magic debug values that you can lookup to see what's going on with your raw pointers while debugging!

See here: In Visual Studio C++, what are the memory allocation representations?

and here: https://en.wikipedia.org/wiki/Magic_number_(programming)#Magic_debug_values

Andrew
  • 5,839
  • 1
  • 51
  • 72
1

If pMyObject->someMethod() ultimately ends up modifying the myObjects list it will invalidate any of the current iterators.

Additionally if the pointer data is already deleted this will trigger the same issue.

1

If you start the program, put a break point at where you create the object. Then add a memory break point. This will fire if you overwrite or delete the memory. Well, or change it in any way.

Your object will look correct if the memory isn't overwritten, but your vtable may not be depending on compiler specifics.

It could also be a size problem if you are using inheritance. If you are using any kind of bucket memory or storing objects by anything but the pointer.

Tavison
  • 1,523
  • 1
  • 11
  • 19