[英]Virtual Destructor causes Access Violation
我正在尝试使 DLL 文件与不同的编译器配置(调试、发布、..)兼容。 In order to make sure that an object is removed the right way I managed to write a pointer wrapper class that uses a compiled delete operator whenever I take an object of the DLL and run out of scope.
我对此非常满意,但是当我尝试删除我在相同的方法/程序中分配的 memory 时,我的程序崩溃了。
以下是在标准发布模式下编译的一些示例代码:
header
template <typename T>
class API mwCompatibleObject
{
public:
//! Constructor
mwCompatibleObject();
//! Destructor
virtual ~mwCompatibleObject();
};
源代码
template < typename T >
mwCompatibleObject< T >::mwCompatibleObject() {}
template <typename T>
mwCompatibleObject<T>::~mwCompatibleObject() {}
注意:API 定义为导出/导入。
现在我在调试模式应用程序中使用这个非常 class 我创建一个实例并立即删除它。
mwCompatibleObject<double> * obj = new mwCompatibleObject<double>();
delete obj;
执行删除操作符会在 mlock.c 第 376 行出现访问冲突。
这是调用堆栈的副本:
ntdll.dll!7721e3be()
[Frames below may be incorrect and/or missing, no symbols loaded for ntdll.dll]
msvcr80d.dll!_unlock(int locknum=4) Line 376 C
msvcr80d.dll!_heap_alloc_dbg(unsigned int nSize=0, int nBlockUse=2968120, const char * szFileName=0x2e2ed26c, int nLine=1638180) Line 477 + 0x7 bytes C++
msvcr80d.dll!_heap_alloc_dbg(unsigned int nSize=0, int nBlockUse=2968120, const char * szFileName=0x2e2ed26c, int nLine=1638180) Line 474 + 0xc bytes C++
00300000()
msvcr80d.dll!malloc(unsigned int nSize=2968120) Line 154 + 0x15 bytes C++
5axutil.dll!100b5d09()
Integrator3.exe!main() Line 54 + 0x34 bytes C++
我不能跳到那行或任何东西,但我设法查看了汇编程序代码,这证明了我的观察,它与析构函数有关。
尝试使 DLL 兼容时,虚拟函数/析构函数是否存在一般问题?
您无法导出模板定义,因为编译器会根据模板的使用情况生成类型。 您只需将它们内联到 header 文件中,或者您可以执行类似的操作,但这需要预先声明您的模板实例化。
还要注意在 C++ 中更喜欢new
和delete
而不是malloc
和 C 中的free
函数,特别是如果你真的想要调用构造函数和析构函数。
编辑:
我会认真考虑模板的内联优于任何导出尝试。 另外,我最初没有注意到只有当您的 class 将是基础 class 或包含虚拟方法时才需要虚拟析构函数。 为什么有一个没有任何内容的 vtable?
template <typename T>
class mwCompatibleObject // no need for export if inlined in header
{
public:
//! Constructor
mwCompatibleObject() {}
//! Destructor (don't need virtual unless it's a base class or has virtual methods)
~mwCompatibleObject() {}
//! Some public method
void DoSomething(const T& withSomething)
{
// ... yata yata
}
private:
T m_member;
};
进一步编辑:
我刚刚发现,当新的 C++ 标准最终确定时,导出模板支持将被完全删除(不弃用,删除)。 header 文件中的内联模板将是编译器将在不久的将来实现并允许的唯一解决方案,因此现在要习惯以这种方式编写它们。 请参阅Herb Sutter 关于 C++0x 的问答
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.