Reputation: 42670
// 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.
However, I Google around and do not see anything mention for std::auto_ptr.
Any workaround?
Upvotes: 1
Views: 702
Reputation: 42670
OK. I realize the root cause. It is caused by
DLL Memory Manager Mixup
allocate a memory from a DLL
return the pointer to EXE
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.
Upvotes: 0
Reputation: 283614
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.
Upvotes: 1
Reputation: 11925
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.
Upvotes: 1
Reputation: 6695
A DLL has its own heap, so you have to make sure you new and delete from the same context.
Upvotes: 4