Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/firebase/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在VC6 dll中使用auto_ptr导致崩溃_C++_Visual C++ - Fatal编程技术网

C++ 在VC6 dll中使用auto_ptr导致崩溃

C++ 在VC6 dll中使用auto_ptr导致崩溃,c++,visual-c++,C++,Visual C++,以下代码在VC9下运行正常。但是,在VC6下,我将立即遇到崩溃,并显示以下消息 调试断言失败 节目: C:\Projects\use\u dynamic\u link\Debug\use\u dynamic\u link.exe 文件:dbgheap.c行:1044 表达方式: _crtisValidHeapPointerUserData 是否不允许在VC6下导出自动ptr 通过DLL导出STL集合类是一个已知的问题 但是,我在谷歌上搜索了一下,没有看到任何关于std::auto_ptr的内容

以下代码在VC9下运行正常。但是,在VC6下,我将立即遇到崩溃,并显示以下消息

调试断言失败

节目: C:\Projects\use\u dynamic\u link\Debug\use\u dynamic\u link.exe 文件:dbgheap.c行:1044

表达方式: _crtisValidHeapPointerUserData

是否不允许在VC6下导出自动ptr

通过DLL导出STL集合类是一个已知的问题

但是,我在谷歌上搜索了一下,没有看到任何关于std::auto_ptr的内容


任何解决方法?

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

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

我的第一个猜测是VC9中的exe和DLL项目被设置为CRT作为共享DLL的目标,当一个或两个VC6项目都以静态CRT非dll为目标时

或者,dll和exe都针对共享CRT dll的不同版本,因此它们实际上使用2个不同的CRT


在VC6中,选中C/C++项目属性的“代码生成”类别中的“运行时库”选项。确保exe和dll都以相同的dll库选项为目标。

我的第一个猜测是,VC9中的exe和dll项目设置为将CRT作为共享dll的目标,而VC6项目中的一个或两个都以静态CRT非dll为目标

或者,dll和exe都针对共享CRT dll的不同版本,因此它们实际上使用2个不同的CRT


在VC6中,选中C/C++项目属性的“代码生成”类别中的“运行时库”选项。确保exe和dll都以相同的dll库选项为目标。

您违反了ODR one定义规则,而且成员函数很可能是内联的-因为它们与std::auto\u ptr的两个不同定义内联,所以您会得到未定义的行为

除此之外,正如Eddy所指出的,当auto_ptr::~auto_ptr释放保留的对象时,它将在EXE中调用运算符delete,而不是在调用运算符new的DLL中调用运算符delete。这种不匹配也会导致崩溃


一般来说,导出仅由纯虚拟函数组成的实现类接口类是非常脆弱的,导出自由工厂函数进行构造是可以的,然后不在类上使用u declspecdllexport,仅在工厂函数上。

您违反了ODR one定义规则,并且成员函数很可能是内联的-因为它们是用std::auto_ptr的两个不同定义内联的,所以您会得到未定义的行为

除此之外,正如Eddy所指出的,当auto_ptr::~auto_ptr释放保留的对象时,它将在EXE中调用运算符delete,而不是在调用运算符new的DLL中调用运算符delete。这种不匹配也会导致崩溃


一般来说,导出仅由纯虚拟函数组成的实现类接口类是非常脆弱的,导出自由工厂函数进行构造是可以的,然后不在类上使用uu declspecdllexport,只在工厂函数上使用。

OK。我意识到了根本原因。这是由于

DLL内存管理器混用

从DLL分配内存

返回指向EXE的指针

尝试从EXE中删除指针

如果我们在选项C/C++->代码生成->使用运行时库下动态链接到运行时库,那么步骤3只能正常工作


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

确定。我意识到了根本原因。这是由于

DLL内存管理器混用

从DLL分配内存

返回指向EXE的指针

尝试从EXE中删除指针

如果我们在选项C/C++->代码生成->使用运行时库下动态链接到运行时库,那么步骤3只能正常工作


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

为什么VC9中没有出现此问题?确定。我确实找到了VC9中没有出现问题的原因。在VC9中,我动态链接到运行时库。在VC6中,我使用静态链接。请参阅我贴出的其他答案。为什么VC9中没有出现此问题?好的。我确实找到了VC9中没有出现问题的原因。在VC9中,我动态链接到运行时库。在VC6中,我使用静态链接。请参阅我发布的其他答案。您的意思是项目设置中的运行时库选项混淆了?您的意思是项目设置中的运行时库选项混淆了?看起来像是鸡蛋和鸡的问题。出于异常安全考虑,我的本能反应是在dll函数返回的指针周围放置一个auto_ptr。但这样我就可以遇到“按不同运行时删除”问题了。@user
:尝试com_ptr_t,并在对象本身中实现释放功能。COM/DCOM/ActiveX使用此方法在模块/编译器/语言/运行时之间共享组件时发挥了巨大作用。看起来像是鸡蛋和鸡的问题。出于异常安全考虑,我的本能反应是在dll函数返回的指针周围放置一个auto_ptr。但是我可能会遇到“按不同运行时删除”问题。@user:尝试com\u ptr\t,并在对象本身中实现一个释放函数。COM/DCOM/ActiveX使用此方法在模块/编译器/语言/运行时之间共享组件时效果非常好。
// 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();
}