使用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集合类。

Access Violation When Accessing an STL Object Through A Pointer or Reference In A Different DLL or EXE

但是,我身边谷歌并没有看到任何提及性病:: auto_ptr的。

任何解决方法?

DLL有自己的堆,所以你必须确保你是新的,并从同一个上下文中删除。

+0

为什么在VC9中不会出现这个问题? – 2010-04-16 07:24:12

+0

好的。我确实发现为什么这个问题不会发生在VC9中。在VC9中,我动态链接到运行时库。在VC6中,我使用静态链接。看到我额外发布的答案。 – 2010-04-17 04:42:28

我的第一个猜测是,将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),只能在工厂功能。

+0

看起来像一个鸡蛋和鸡的问题。由于异常安全,我的自然反射会在dll函数返回的指针周围放置一个auto_ptr。但是,然后我可以遇到不同运行时问题的删除。 – user331471 2011-07-26 14:05:05

+0

@user:尝试'com_ptr_t',并在对象本身中实现'Release'函数。 COM/DCOM/ActiveX使用此方法可以很好地共享模块/编译器/语言/运行时间之间的组件。 – 2011-07-26 16:04:24

好的。我意识到根本原因。它是由

DLL内存管理器造成的mixup

DLL memory manager mixup

  1. 分配从DLL

  2. 返回指针内存为EXE

  3. 尝试删除来自EXE的指针

步骤(3)将只正常工作,如果我们链接到动态运行时库(下选择C/C++ - >代码生成 - >使用运行时库)

如果我们链接运行时库静态地,DLL使用的内存管理器可能与EXE使用的内存管理器不同。

+0

你的意思是项目设置中的运行时库选项混淆了? – 2010-04-16 08:27:51

+0

看到我编辑的帖子。 – 2010-04-17 04:41:16