Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42670

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 Google around and do not see anything mention for std::auto_ptr.

Any workaround?

Upvotes: 1

Views: 702

Answers (4)

Cheok Yan Cheng
Cheok Yan Cheng

Reputation: 42670

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.

Upvotes: 0

Ben Voigt
Ben Voigt

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

sean e
sean e

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

Eddy Pronk
Eddy Pronk

Reputation: 6695

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

Upvotes: 4

Related Questions