Win32调试构建中,什么原因会导致VTable指针为0xdddddddd?

14

我正在调试一个问题,并将其缩小到对象的虚函数表指针为 0xdddddddd。 这个答案表明Win32 debug builds通常会将已被删除或未使用的内存设置为这个特殊值。

注意,指针本身看起来是有效的,只是虚函数表指针0xdddddddd

这是一段代码片段:

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     
}
如果我在访问冲突行处中断程序,并查看pMyObject,则可以看到pMyObject本身具有有效地址(0x08ede388),但是__vfptr成员无效(0xdddddddd)。

一些注意事项:
  • 这是单线程应用程序,因此这很可能不是竞争条件或互斥问题。
  • 似乎没有任何明显的问题,比如在访问对象之前在调用堆栈中进一步删除该对象。
  • 此问题似乎仅可在Windows 2008服务器上重现,而在Windows 7上无法重现。
有关如何进一步调试此问题的建议?

这看起来像是某人在将指针放入列表后删除了对象的典型情况。你确定不是这种情况吗?(它可能被从填充列表后的一些其他函数中删除,因此查看调用堆栈可能没有什么帮助)。最简单的尝试方法是在IMyObject的析构函数中设置断点并查看是否有人删除了对象。 - Naveen
4个回答

13

您在释放指针后继续使用了它。在析构函数中设置断点以获取堆栈跟踪并查看是谁删除了它。或者更好的方法是使用shared_ptr<>来避免这个问题。


谢谢,这些对象被创建/销毁了数千次,所以这可能会很困难(甚至不确定条件断点是否有帮助,因为我不确定条件是什么)。但我会开始调查。 - LeopardSkinPillBoxHat
2
你正在寻找这样一种情况:对象被删除,但指针未从列表中移除;或者一个对象可能被插入到列表中多次,但在删除时只从列表中移除一次。 - janm
@LeopardSkinPillBoxHat:...或者一个对象被添加到列表中,然后在列表之外被删除的情况。简单的方法是避免使用裸指针,而是存储可用的智能指针之一(QSharedPointer可能是一个不错的选择)。 - David Rodríguez - dribeas

2
如果您启动程序,请在创建对象的位置设置断点。 然后添加内存断点。 如果您覆盖或删除内存,它将触发。 好吧,或以任何方式更改它。
如果内存没有被覆盖,您的对象看起来正确,但是根据编译器规范,您的虚函数表可能不正确。
如果您使用继承,则还可能存在大小问题。 如果您正在使用任何类型的桶式内存或按指针以外的方式存储对象。

2
如果pMyObject->someMethod()最终修改了myObjects列表,它将使任何当前的迭代器无效。
另外,如果指针数据已经被删除,这也会触发相同的问题。

啊,无效的迭代器!我没有想到过。 - Andrew

2

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接