Removing an object created in a DLL

I need some clarification regarding the runtime / heap problems when deleting an object that was created in the DLL. I need some insight before I come to my questions ...

In my project, the DLL (indicated by its name) returns a new Grabber object. In an earlier version of my code, the DLL exported this function:

extern "C" __declspec(dllexport) Grabber* CreateGrabber(string settings) { return new SomeSpecificGrabber(settings); } 

In EXE, I used a static function like this to create a new Grabber object:

 static Grabber* createGrabberObject(const std::string& grabberType, const std::string& grabberSettings) { FARPROC hProc = 0; // load dll with the name of grabberType HMODULE hDLL = LoadLibrary(grabberType.c_str()); // get address for CreateGrabber function hProc = GetProcAddress(hDLL, "CreateGrabber"); // instantiate a function pointer of our type and typecast the address // of the CreateGrabber function to this type CreateGrabberFunctionType CreateGrabberFunction = (CreateGrabberFunctionType)hProc; // call CreateGrabber in DLL to get a Grabber object return CreateGrabberFunction(grabberSettings); } 

In EXE, the lifetime of a Grabber object is controlled by a smart pointer:

 shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings")); 

All this worked fine as long as I compiled the EXE and DLL using the /MDd (VC ++ 2010), which means that the EXE and DLL used the same heap.

Now I want to compile my solution using the /MTd . With this, I got a runtime statement of type _CrtIsValidHeapPointer for the settings string object that I passed to the DLL. This makes sense because the DLL is trying to remove the string object that was created in the EXE. And they no longer use the same heap.

I ran into this problem by slightly changing the exported DLL function ( const char* instead of string ):

 extern "C" __declspec(dllexport) Grabber* CreateGrabber(const char* settings) { return new SomeSpecificGrabber(settings); } 

And in createGrabberObject I pass grabberSettings.c_str() instead of grabberSettings DLL function.

Now everything is working fine. But now my first question appears. Why don't I get the _CrtIsValidHeapPointer statement when myGrabberObj is removed? The object was created from a DLL, but removed from the EXE (using a smart pointer). Why don't I have the same problem here as with the string object above?

I think the clean solution would be that the DLL also exports such a function:

 extern "C" __declspec(dllexport) void DeleteGrabber(Grabber* grabber) { delete grabber; } 

Then I would also have a static function in the EXE that calls DeleteGrabber in the DLL:

 static void deleteGrabberObject(const std::string& grabberType, Grabber* grabber) { FARPROC hProc = 0; // load dll with the name of grabberType HMODULE hDLL = LoadLibrary(grabberType.c_str()); // get address for DeleteGrabber function hProc = GetProcAddress(hDLL, "DeleteGrabber"); // instantiate a function pointer of our type and typecast the address // of the DeleteGrabber function to this type DeleteGrabberFunctionType DeleteGrabberFunction = (DeleteGrabberFunctionType)hProc; // call DeleteGrabber in DLL DeleteGrabberFunction(grabber); } 

This static function can be automatically called by a smart pointer:

 shared_ptr<Grabber> myGrabberObj = shared_ptr<Grabber>(createGrabberObject("SomeGrabber.DLL", "Settings"), boost::bind(deleteGrabberObject, "SomeGrabber.DLL", _1)); 

This also works. But here is my second question : the static functions createGrabberObject and deleteGrabberObject load the DLL. Does this mean that two different heaps are created because two instances of the DLL are loading (then this solution would not solve my problem at all)? Or are these two static functions using the same heap?

Hope someone can explain what is going on here ...

+7
source share
3 answers

The DLL refers to the link, does not load twice, and when you use LoadLibrary, then it loads only once, and they will use the same heap. Static function is a normal solution to this problem.

+5
source

For your second question, just because you load the DLL twice does not mean there are two instances. The OS is smart enough to load it only once.

EDIT: for the first question, this is due to the fact that either the common pointer never goes out of scope, or because the VC runtime cannot correctly identify the case (it did not fatally fail, but the memory was not freed).

+3
source

Well, this is because (in your case) two heaps work. There is another heap manager in the DLL, and the EXE is different. This may be due to:

  • Debugging / Release Failure
  • The VC runtime is used (one is VC8, for example, VC9). Difficult and higher!
  • Various models used to build DLL / EXE ( /MT[d] flag, link as static-lib, etc.).
  • You showed delete against new , which is valid. But this may also be the case when new is actually malloc / HeapAlloc.

In short, the memory allocated by the cumulus manager X will not be found with the help of the heap manager Y , and therefore the statement!

+3
source

All Articles