tags:

views:

111

answers:

4
// 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.

http://stackoverflow.com/questions/2451714/access-violation-when-accessing-an-stl-object-through-a-pointer-or-reference-in-a

However, I Google around and do not see anything mention for std::auto_ptr.

Any workaround?

+4  A: 

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

Eddy Pronk
Why the problem doesn't occur in VC9?
Yan Cheng CHEOK
OK. I do find out why the problem doesn't occur in VC9. In VC9, I am dynamically link to run time library. In VC6, I am using static link. See my additional posted answer.
Yan Cheng CHEOK
+1  A: 

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.

sean e
+1  A: 

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.

Ben Voigt
A: 

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

DLL Memory Manager Mixup

http://stackoverflow.com/questions/1085873/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.

Yan Cheng CHEOK
You mean the run time library options in the project settings were mixed up?
sean e
See my edited post.
Yan Cheng CHEOK