开发者

Use auto_ptr in VC6 dll cause crash

// 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();
}

The following code run perfectly OK under VC9. However, under VC6, I will experience an immediate crash with the following message.

Debug Assertion Failed!

Program: C:\Projects\use_dynamic_link\Debug\use_dynamic_link.exe File: dbgheap.c Line: 1044

Expression: _CrtIsValidHeapPointer(pUserData)

Is it exporting auto_ptr under VC6 is not allowed?

It is a known problem that exporting STL collection classes through DLL.

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

However, I开发者_StackOverflow中文版 Google around and do not see anything mention for std::auto_ptr.

Any workaround?


A DLL has its own heap, so you have to make sure you new and delete from the same context.


My first guess would be that the exe and dll projects in VC9 are set up for the CRT to be targeted as a shared dll, while one or both of the VC6 projects is targeting the static CRT (non-dll).

Alternatively, both the dll and exe are targeting different versions of a shared CRT dll (so they actually use 2 different CRTs).

In VC6, check the run-time library option in the Code Generation category of the C/C++ Project properties. Make sure both the exe and dll target the same DLL library option.


You're violating the ODR (one definition rule) and most likely the member functions are inlined -- since they are inlined with two different definitions of std::auto_ptr you get undefined behavior.

On top of that, as Eddy points out, when auto_ptr::~auto_ptr frees the held object, it will call operator delete in the EXE instead of in the DLL where operator new was called. This mismatch can also produce a crash.

In general it is very fragile to export implemented classes (interface classes consisting solely of pure virtual functions, and exporting a free factory function for construction) are OK and then you don't use __declspec(dllexport) on the class, only on the factory function.


OK. I realize the root cause. It is caused by

DLL Memory Manager Mixup

DLL memory manager mixup

  1. allocate a memory from a DLL

  2. return the pointer to EXE

  3. try to delete pointer from EXE

Step (3) will only work fine, if we link to run-time library dynamically (under options C/C++ -> Code Generation -> Use run-time library)

If we link to run-time library statically, the memory manager used by DLL, might be different from the memory manager used by EXE.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜