使用auto_ptr DLL引起死机
// dll
#include <memory>
__declspec(dllexport) std::auto_ptr<int> get();
__declspec(dllexport) std::auto_ptr<int> get()
{
return std::auto_ptr<int>(new int());
}
// exe
#include <iostream>
#include <memory>
__declspec(dllimport) std::auto_ptr<int> get();
int main() {
{
std::auto_ptr<int> x = get();
}
std::cout << "done\n";
getchar();
}
下面的代码运行在VC9完全确定。但是,在VC6下,我将遇到以下消息的立即崩溃。使用auto_ptr DLL引起死机
Debug Assertion Failed!
计划: C:\项目\ use_dynamic_link \调试\ use_dynamic_link.exe 文件:dbgheap.c行:1044
表达: _CrtIsValidHeapPointer(pUserData)
它是出口的auto_ptr下VC6是不允许的?
这是一个已知的问题,即通过DLL导出STL集合类。
但是,我身边谷歌并没有看到任何提及性病:: auto_ptr的。
任何解决方法?
DLL有自己的堆,所以你必须确保你是新的,并从同一个上下文中删除。
我的第一个猜测是,将VC9中的exe和dll项目设置为将CRT作为共享dll,而其中一个或两个VC6项目都是针对静态CRT(非dll)。
或者,dll和exe都是针对不同版本的共享CRT dll(因此它们实际上使用2个不同的CRT)。
在VC6中,检查C/C++项目属性的代码生成类别中的运行时库选项。确保exe和dll都以相同的DLL库选项为目标。
您违反了ODR(一个定义规则),并且很可能会将内联函数内联 - 因为它们被内联了std::auto_ptr
的两个不同定义,您将得到未定义的行为。
最重要的是,作为艾迪指出,当auto_ptr::~auto_ptr
释放的对象举行,它会调用operator delete
的EXE,而不是在operator new
被称为DLL。这种不匹配也会导致崩溃。
一般来说,导出已实现的类(纯粹由纯虚函数组成的接口类,以及导出一个免费的工厂函数进行构建)是非常脆弱的,然后您不要在类上使用__declspec(dllexport)
,只能在工厂功能。
看起来像一个鸡蛋和鸡的问题。由于异常安全,我的自然反射会在dll函数返回的指针周围放置一个auto_ptr。但是,然后我可以遇到不同运行时问题的删除。 – user331471 2011-07-26 14:05:05
@user:尝试'com_ptr_t',并在对象本身中实现'Release'函数。 COM/DCOM/ActiveX使用此方法可以很好地共享模块/编译器/语言/运行时间之间的组件。 – 2011-07-26 16:04:24
好的。我意识到根本原因。它是由
DLL内存管理器造成的mixup
分配从DLL
返回指针内存为EXE
尝试删除来自EXE的指针
步骤(3)将只正常工作,如果我们链接到动态运行时库(下选择C/C++ - >代码生成 - >使用运行时库)
如果我们链接运行时库静态地,DLL使用的内存管理器可能与EXE使用的内存管理器不同。
你的意思是项目设置中的运行时库选项混淆了? – 2010-04-16 08:27:51
看到我编辑的帖子。 – 2010-04-17 04:41:16
为什么在VC9中不会出现这个问题? – 2010-04-16 07:24:12
好的。我确实发现为什么这个问题不会发生在VC9中。在VC9中,我动态链接到运行时库。在VC6中,我使用静态链接。看到我额外发布的答案。 – 2010-04-17 04:42:28