C Board  

Go Back   C Board > General Programming Boards > C++ Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 09-08-2004, 07:14 AM   #1
Confused
 
Magos's Avatar
 
Join Date: Sep 2001
Location: Sweden
Posts: 3,125
DLL and std::string woes!

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?
__________________
MagosX.com

Give a man a fish and you feed him for a day.
Teach a man to fish and you feed him for a lifetime.

Last edited by Magos; 09-08-2004 at 07:16 AM.
Magos is offline   Reply With Quote
Old 09-08-2004, 08:29 AM   #2
&TH of undefined behavior
 
Fordy's Avatar
 
Join Date: Aug 2001
Posts: 5,219
What compiler are you using?

It seems to work either way for me on VC++7
__________________
"If A is success in life, then A equals x plus y plus z. Work is x; y is play; and z is keeping your mouth shut."
Albert Einstein (1879 - 1955)


Board Rules
Fordy is offline   Reply With Quote
Old 09-08-2004, 08:34 AM   #3
Confused
 
Magos's Avatar
 
Join Date: Sep 2001
Location: Sweden
Posts: 3,125
Vc++6 :/
__________________
MagosX.com

Give a man a fish and you feed him for a day.
Teach a man to fish and you feed him for a lifetime.
Magos is offline   Reply With Quote
Old 09-08-2004, 08:45 AM   #4
&TH of undefined behavior
 
Fordy's Avatar
 
Join Date: Aug 2001
Posts: 5,219
Have you tried as I suggested before and had the function return a char array as opposed to a std::string? I know you dont like the practicalities of that, but see if it makes a difference
__________________
"If A is success in life, then A equals x plus y plus z. Work is x; y is play; and z is keeping your mouth shut."
Albert Einstein (1879 - 1955)


Board Rules
Fordy is offline   Reply With Quote
Old 09-08-2004, 09:20 AM   #5
and the hat of marbles
 
Sang-drax's Avatar
 
Join Date: May 2002
Location: Lund, Sweden
Posts: 2,041
You cannot share STL data between modules in VC++6. The STL implementation uses class-static members, which will differ between modules (DLL and EXE).

Use a different STL and you will be fine.

There is a knowledge-base article about this somewhere.
__________________
Last edited by Sang-drax : Tomorrow at 02:21 AM. Reason: Time travelling
Sang-drax is offline   Reply With Quote
Old 09-08-2004, 09:32 AM   #6
&TH of undefined behavior
 
Fordy's Avatar
 
Join Date: Aug 2001
Posts: 5,219
Quote:
Originally Posted by Sang-drax
You cannot share STL data between modules in VC++6. The STL implementation uses class-static members, which will differ between modules (DLL and EXE).

Use a different STL and you will be fine.

There is a knowledge-base article about this somewhere.
http://support.microsoft.com/default...NoWebContent=1
__________________
"If A is success in life, then A equals x plus y plus z. Work is x; y is play; and z is keeping your mouth shut."
Albert Einstein (1879 - 1955)


Board Rules
Fordy is offline   Reply With Quote
Old 09-08-2004, 10:26 AM   #7
Confused
 
Magos's Avatar
 
Join Date: Sep 2001
Location: Sweden
Posts: 3,125
Quote:
Have you tried as I suggested before and had the function return a char array as opposed to a std::string?
Yes, returning a const char* seems to work fine.

Quote:
Use a different STL and you will be fine.
Different STL? What do you mean?

Quote:
http://support.microsoft.com/defaul...&NoWebContent=1
The suggested workaround ( http://support.microsoft.com/default...b;EN-US;168958 ) is a bit confusing. You cannot use the __declspec(dllexport) template class on a std::string like you can on a std::vector or other container. Any suggestions? Or is my only hope to either upgrade to VC7.0 (or whatever version is the current one) or degrade to returning char pointers (yuck)?
__________________
MagosX.com

Give a man a fish and you feed him for a day.
Teach a man to fish and you feed him for a lifetime.
Magos is offline   Reply With Quote
Old 09-08-2004, 12:34 PM   #8
Registered User
 
Codeplug's Avatar
 
Join Date: Mar 2003
Posts: 3,903
>> Use a different STL [implementation] and you will be fine.
Like STL Port

You should also be aware of this knowledge base article as well.

Because of all these issues, I personally don't allow STL or CRT objects to cross module boundaries. I don't mind allowing allocated memory to cross module boundaries as long as the allocation and dealloction is done in the same module.

gg

Last edited by Codeplug; 09-08-2004 at 12:36 PM.
Codeplug is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
How to solve warnings that appear when building my DLL... starcatcher Windows Programming 6 12-14-2008 11:47 AM
Need Partners (D&D fan preferably) C_ntua Game Programming 44 11-22-2008 09:21 AM
dll testing axr0284 Windows Programming 1 03-26-2006 10:25 PM
Pipe the console from a DLL loobian Windows Programming 12 11-30-2003 08:55 PM
std::string vs char* DLL problem aker_y3k C++ Programming 13 10-02-2002 09:05 AM


All times are GMT -6. The time now is 12:30 AM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22