基类虚拟析构函数访问冲突
抱歉,如果已经有人问过这个问题,但我很难搜索析构函数和访问冲突 =)
这是场景的 C++ 伪代码:
在 DLL1 中(使用 /MT 编译)
class A
{
public:
virtual ~A() <== if "virtual" is removed, everthing works OK
{
}
}
class B : public A
{
public:
__declspec( dllexport ) ~B() // i did try without exporting the destructor as well
{
} <== Access Violation as it returns (if fails in assembly at delete operator...)
}
在链接到 DLL1 的 DLL2 中
main()enter code here
{
B* b = new B();
delete b; <== Access Violation
}
发生了什么?我是不是脑子有问题?如果我将 A 的析构函数设为非虚拟,则一切正常 - 甚至 A 和 B 的析构函数也会被调用(就好像 A 的析构函数是虚拟的 - 这是因为它是公共的吗?)。
我的主要问题是——当基类的析构函数被声明为虚拟时,为什么会出现访问冲突?
Sorry if this was asked already, but I had a hard time searching for destructor and access violation =)
Here's C++ pseudo-code the scenario:
In DLL1 (compiled with /MT)
class A
{
public:
virtual ~A() <== if "virtual" is removed, everthing works OK
{
}
}
class B : public A
{
public:
__declspec( dllexport ) ~B() // i did try without exporting the destructor as well
{
} <== Access Violation as it returns (if fails in assembly at delete operator...)
}
In DLL2 which links to DLL1
main()enter code here
{
B* b = new B();
delete b; <== Access Violation
}
What is going on? Am I having a brain shart? If I make A's destructor non-virtual, everything works OK - even A and B's destructor get called (as if A's destructor was virtual - is this due to the fact that it's public?).
My main question though - is why is there an access violation when the base classe's destructor is declared as virtual?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
谢谢你们!谢谢 ChrisW.. 看来这正是发生的事情。
我唯一需要添加的其他东西是静态分配器(static createNew()):(
考虑到我的部署环境,使用 /MD 编译对我来说不是一个选项)
Thanks guys! Thanks ChrisW.. looks like that's exactly what's happening.
Only other thing I needed to add was a static allocator (static createNew()):
(btw compiling with /MD is not an option for me given my deployment environment)
因为它在删除运算符中崩溃,并且因为您说您正在使用
/MT
进行编译,所以我相信原因是您的两个 DLL 不共享相同的堆:因为它们各自链接到静态库,它们各自获得自己的运行时堆的私有副本;您可以有效地从一个堆中分配一个 DLL 中的内存,并从另一堆中删除另一个 DLL 中的内存。要解决此问题,您可以声明析构函数受到保护,并且不导出它。相反,创建一个静态销毁函数:
或者,您可能更喜欢这样做,因为它不涉及更改源代码,请确保两个 DLL 都构建为使用相同的堆,即使用 C 运行时的 DLL 版本,这我认为意味着使用
/MD
选项而不是/MT
。Because it's crashing in the delete operator, and because you said you're compiling with
/MT
, I believe that the cause is that your two DLLs don't share the same heap: because they're each linking to a static library, they're each getting their own private copy of the run-time heap; and you're effectively allocating memory in one DLL from one heap, and deleting the memory in another DLL from another heap.To work-around this, you can declare that the destructor is protected, and don't export it. Instead, create a static destroy function:
Alternatively, and you may prefer this because it doesn't involve changing the source code, ensure that both DLLs are build to use the same heap, i.e. using the DLL versions of the C-runtime, which I think means using the
/MD
option instead of/MT
.