After a lot of testing and searching I've managed to make a short program containing the error. I have a program that loads a DLL with a class that has a method that returns an std::string. Now, the problem is if the stirng is destroyed before FreeLibrary() is called everything is fine, but if it's destroyed after FreeLibrary() is called the program crashes.
Here is the public header for the DLL:
(DllPublic.h)
Code:
#ifndef DLL
#ifdef DLL_EXPORT
#define DLL __declspec(dllexport)
#else
#define DLL __declspec(dllimport)
#endif
#endif
#include <windows.h>
#include <string>
class StringClass
{
public:
virtual std::string GetString() = 0;
};
typedef StringClass* (*FUNCTION_CREATE)(VOID);
typedef VOID (*FUNCTION_DESTROY)(StringClass*);
extern "C" DLL StringClass* CreateStringClass();
extern "C" DLL VOID DestroyStringClass(StringClass* Object);
Here is the DLL header only used when compiling the DLL:
(Dll.h)
Code:
#include "DllPublic.h"
class DllStringClass : public StringClass
{
public:
DllStringClass();
virtual std::string GetString();
private:
std::string String;
};
Here is the body for the DLL:
(Dll.cpp)
Code:
#define DLL_EXPORT
#include "Dll.h"
DllStringClass::DllStringClass()
{
String = "Some random string!";
}
std::string DllStringClass::GetString()
{
return String;
}
extern "C" DLL StringClass* CreateStringClass()
{
return new DllStringClass;
}
extern "C" DLL VOID DestroyStringClass(StringClass* Object)
{
delete Object;
}
Now, consider these two testprograms. I use dynamic memory for the std::string to easier see when it is destroyed. It makes no difference if it was created staticly.
This program, where the std::string destructor is called before FreeLibrary() runs fine and as expected:
Code:
#include "Dll\\DllPublic.h"
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
HINSTANCE Dll = LoadLibrary("Dll.dll");
std::string* S = new std::string;
FUNCTION_CREATE Create = reinterpret_cast<FUNCTION_CREATE>(GetProcAddress(Dll, "CreateStringClass"));
FUNCTION_DESTROY Destroy = reinterpret_cast<FUNCTION_DESTROY>(GetProcAddress(Dll, "DestroyStringClass"));
StringClass* SC = Create();
(*S) = SC->GetString();
Destroy(SC);
MessageBox(NULL, S->c_str(), "Message", MB_OK);
delete S;
FreeLibrary(Dll);
return 0;
}
...but if you delete it after FreeLibrary you get a crash:
Code:
#include "Dll\\DllPublic.h"
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, INT)
{
HINSTANCE Dll = LoadLibrary("Dll.dll");
std::string* S = new std::string;
FUNCTION_CREATE Create = reinterpret_cast<FUNCTION_CREATE>(GetProcAddress(Dll, "CreateStringClass"));
FUNCTION_DESTROY Destroy = reinterpret_cast<FUNCTION_DESTROY>(GetProcAddress(Dll, "DestroyStringClass"));
StringClass* SC = Create();
(*S) = SC->GetString();
Destroy(SC);
MessageBox(NULL, S->c_str(), "Message", MB_OK);
FreeLibrary(Dll);
delete S;
return 0;
}
Um, why? Suggestions? Solutions? Help?