【发布时间】:2011-03-23 08:08:12
【问题描述】:
我有一些代码在大型系统中崩溃。 但是,代码本质上归结为以下伪代码。 我已经删除了很多细节,因为我试图将其归结为裸露的骨头; 不过,我认为这并没有遗漏任何重要的内容。
// in a DLL:
#ifdef _DLL
#define DLLEXP __declspec(dllexport)
#else
#define DLLEXP __declspec(dllimport)
#endif
class DLLEXP MyClass // base class; virtual
{
public:
MyClass() {};
virtual ~MyClass() {};
some_method () = 0; // pure virtual
// no member data
};
class DLLEXP MyClassImp : public MyClass
{
public:
MyClassImp( some_parameters )
{
// some assignments...
}
virtual ~MyClassImp() {};
private:
// some member data...
};
和:
// in the EXE:
MyClassImp* myObj = new MyClassImp ( some_arguments ); // scalar new
// ... and literally next (as part of my cutting-down)...
delete myObj; // scalar delete
请注意,正在使用匹配的标量 new 和标量删除。
在 Visual Studio (2008 Pro) 的调试版本中,
在微软的
_ASSERTE(_CrtIsValidHeapPointer(pUserData));
堆栈顶部附近有以下项目:
mydll_d.dll!operator delete()
mydll_d.dll!MyClassImp::`vector deleting destructor'()
我觉得应该是这样的
mydll_d.dll!MyClassImp::`scalar deleting destructor'()
也就是说,程序的行为就像我写的一样
MyClassImp* myObj = new MyClassImp ( some_arguments );
delete[] newObj; // array delete
pUserData 中的地址是myObj 本身的地址(而不是成员)。
该地址周围的内存如下所示:
... FD FD FD FD
(address here)
VV VV VV VV MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
FD FD FD FD AB AB AB AB AB AB AB AB EE FE EE FE
...
其中四个VV想必是虚函数表的地址,
MM...MM 是可识别的成员数据,
其他字节是调试器放置的各种特殊标记
(例如,FD FDs 是对象存储周围的“保护字节”)。
在断言失败前不久,我确实看到了 VVs 的变化,
并想知道这是否是由于切换到基类的虚函数表所致。
我知道正在销毁的类层次结构中的错误级别的问题。 这不是这里的问题。我的析构函数都是虚拟的。
我注意到微软的页面 “BUG:为导出的类调用了错误的运算符删除” http://support.microsoft.com/kb/122675 但这似乎与试图对破坏数据负责的错误可执行文件(使用错误的堆)有关。
在我的情况下,删除析构函数的错误“风味”似乎正在被应用: 即向量而不是标量。
我正在尝试生成仍然存在问题的最小缩减代码。
但是,任何有助于进一步调查此问题的提示或技巧将不胜感激。
也许这里最大的线索是堆栈上的mydll_d.dll!operator delete()。
我应该期望这是myexe_d.exe!operator delete(),
表示DLLEXPs 已经“丢失”了?
我想这可能是双重删除的一个实例(但我不这么认为)。
关于_CrtIsValidHeapPointer 检查的内容,我是否可以阅读一个很好的参考资料?
【问题讨论】:
-
在 MyClassImp 中,ctor 和 dtor 可能被称为 MyClassImp 而不是 MyClass,不是吗?
-
哦,你可以在 new() 中按 F11 吗?是哪一个?
-
@Calvin1602 [1] 谢谢,是的——我现在已经更正了。 [2] 被调用的 c'tor 是
MyClassImp在MyClass被调用之后/期间的那个。 -
一旦您开始从 DLL 导出类,使用 /MD 编译就变得非常重要。在我看来像 /MT。
-
@Hans - 这也是一个线索。也许您应该将其添加为答案,而不仅仅是评论。
标签: c++ debugging visual-c++ msvcrt destructor