How can I ensure a dll is not unloaded while any objects in it exist?
The problem is, when I was using explict memory management I could delete the dll objects before freeing the dll, however with smart pointers I have no controll over the order there destroyed, meaning the dll may be freed first causeing a crash when trying to free one of the other objects:
FlPtr is a simple refrence counting class thats calls AddRef and Release as needed
ExampleDll *dll = LoadDll(L"bin\\example.dll");
IObject *obj = dll->CreateObject();
...
obj->Release();
delete dll;//fine because all objects already deleted
return 0;
auto_ptr<ExampleDll> dll = LoadDll(L"bin\\example.dll");
FlPtr<IObject> obj = dll->CreateObject();
...
return 0;//crash if dll is destructed before obj since Object::Release needs to call into the dll
I tried making the dll handle unloading itsself, ie only unload after all objects have been deleted. This work by creating a new object IExampleDll which the dll implements. This is like the ExampleDll object from before but lives in the dll rather than the exe and is also refrence counted. Each object in the dll increments this refrence on contruction and deincrements it on destruction. This means the refrence count only reaches zero when the exe has Released its refrences AND all the dlls objects have been destroyed. It then deletes itsself calling FreeLibrary(GetModuleHandle()) in its destructor.
This however crashes at the FreeLibrary, im asuming because the thread is still in the dlls code that is being unloaded...
I'm at a loss now how to make sure the dll is only unloaded when there are no remaining objects, apart from going back to freeing the dll explicitly after everything else should have been deleted;
int main()
{
ExampleDll *dll = LoadDll("bin\\example.dll");
restOfProgram();
delete dll;
}
This approach becomes difficult when dlls need to be loaded/unloaded mid program saftly, ie if the user changed from d3d to openGL in options.
Assuming you do not want to terminate the thread when unloading the library (otherwise, see MSalters), you need to free the library from the caller that loaded it.
COM solves that by an in-DLL instance counter (much like yours, if I understand you correctly), and regulary checking it by calling a global exported CanUnloadNow function.
Another option is to have your object/interface smart pointers ALSO reference the DLL they came from. This would increase the client data size, but you wouldn't need to touch the DLL. You might even recycle the LoadLibrary/FreeLibrary reference counter, however that might hit performance.
Also, none of these schemes help much if you get circular DLL dependencies (Component DllA.X references DllB.Y, which references DllA.Z). I haven't yet fould a good solution to that that doesn#t requrie global knowledge.
For the case where the DLL is switched at run time, I'd avoid the smart pointer system for objects created by the DLL and use a system like this:
|-----------------------| |--------------------------|
| Abstraction Interface | | Implementation Interface |
|-----------------------| |--------------------------|
^ ^
| |
|-------------|1 *|-------------------|* *|----------------|
| Application |-------| Abstraction Layer |--------| Implementation |
|-------------| |-------------------| |----------------|
\------------- Main Program ------------------/ \-------- DLL --------/
The application holds a list of all the allocated abstraction layer objects. The abstraction layer objects are the only objects that are allowed to own pointers to objects created by the implementation layer. When swapping DLLs, first iterate all abstraction layer objects and tell them to release the implementation specific data. Then unload the DLL and load the new DLL. Then iterate the abstraction layer objects again and tell them to create new implementation specific data.
MSDN is explicit on this topic: "A thread that must unload the DLL in which it is executing and then terminate itself should call FreeLibraryAndExitThread instead of calling FreeLibrary and ExitThread separately. Otherwise, a race condition can occur. For details, see the Remarks section of FreeLibraryAndExitThread.
Ok I think the best choice is to use the COM approach of polling the dll to see if it can be unloaded. How can I go about doing this though so that I can continue polling the dll after everything else has closed down (ie the main thread has terminated)? Do I need to create a completly seperate process to do this, in which case how do I do it so this seperate process knows about all the loaded dlls, and in a way which has VERY little impact on proformance?
Mayby I could just create the polling system when all the DllPtr's are out of scope and terminate it as soon as it has free the dll? That way it only exists for as long as it takes for any remaing smart pointers to be destroyed.
Related
I did solve my immediate problem at hand, but now I need to understand why it is solved. ;-)
So here I have couple more questions.
Suppose I have a class that is being exported from the DLL. Now this DLL should be loaded into the memory every time I call:
MyExportedClass *pb = new MyExportedClass;
and it should stay in memory and becomes unloaded only when I call:
delete pb;
Is this correct?
If I understood this correctly and the answer to the previous question is yes, then what should happen in the following scenario:
I have an interface which exported from the dll (dll1) and I have its implementation which is exported from another dll (dll2). So every time I execute:
MyInterface *pInterface = new MyImplementation;
both those dlls should be loaded in memory and they should stay in memory until I call:
delete pInterface;
Is this correct?
Now, if the answer to this question is yes - do I have a control/saying, which library will be unloaded first and which one will be second? Or the unload will always happen right after calling destructor of the appropriate class?
Now, is there a tool which checks if the library becomes unloaded and at which point? I can probably just use the fake DllMain() and check its process_detach case, but my impression always was: use DllMain when the library exports function and don't use DllMain when the library exports classes. I used this approach since MSVC 5/6 (following one of the books about C++).
Was I wrong and I can still use DLLMain in both cases?
Thank you.
DLL loading can be automatic (if listed in the import table) or manual (using LoadLibrary). Some managed frameworks, like .NET, will silently call LoadLibrary for you when they see a DLL import declaration in their metadata, but C++ is not one of these. The closest thing C++ has is delay-loading, where the function that calls LoadLibrary is (by default, you can substitute your own) provided by the compiler.
On the other hand, DLL unloading is always manual. Deleting an object never implicitly unloads a DLL. You have to call FreeLibrary (or FreeLibraryAndExitThread). And you had better not call FreeLibrary while objects defined in that library are still in use.
Now, the COM system in Windows is a bit more complicated, because it manages DLL lifetime for you. But DLL lifetime is still not controlled by object deletion, rather by calling a DllCanUnloadNow function in the DLL. Usually you need to maintain a count of active objects in order to write that function correctly. But it still requires your manual implementation, and you can simply always return false to never unload (this is a bit of a pain during development because you have to close the entire application to try a new plugin version, etc... but actually freeing every usage of a DLL and successfully unloading it is rare anyway)
And certainly there is nothing that will automatically unload a DLL listed in the import table, those get loaded during process startup and never unloaded, no matter how many object instances are created or destroyed.
I have a huge program (A) which uses about 30 (most of my own, some 3rd party) dll´s. It uses ActiveX, ATL and MFC to do different stuff. Now i want to use wxWidgets for some special tasks and will call the wxWidgets dialogs from within the program. I can do this with a special designed DLL which takes the wxW.. parts. But to run the special tasks with or without the A programm i would to like to put the wxW.. stuff in an exe (B) and these exe should address the same data from the A program. As far as i know each *.exe has its own process and so i can not share the same pointer address.
I can put in some shared data block in one of the DLLs.
#pragma data_seg("SHARED")
CClassA *g_ClassAPointer=NULL;
#pragma data_seg()
#pragma comment(linker, "/section:SHARED,RWS")
If the A is running and starts B, i can get the pointer g_ClassAPointer with the address within A. Is there a way to get the address or get an offset to reach this address within B ?
Thanks in advance,
Howie
BTW: We also want to use wxWidgets to fade all the MFC stuff more and more to cross platform code otherwise i would stick to MFC or use the wxW - DLL within a wrapper *.exe.
You're looking for shared memory, and the usual way to create that is via CreateFileMapping. This can create shared memory backed by a named file, or backed by the paging file. (Memory allocated by GlobalAlloc is also backed by the paging file, so that's no unusual thing).
In either case, the memory block from CreateFileMapping is named, so another process can access the shared memory block by calling OpenFileMapping with the same name.
Keep in mind that the shared memory block might reside at different offsets in memory. Also, if you put CClassA in shared memory, there's no automatic mechanism to ensure that all pointers inside CClassA point to the same shared memory block. E.g. putting a std::string or MFC CString in shared memory is unlikely to achieve what you intended.
So I have a DLL I wrote in C++.
However, it allocates memory using GlobalAlloc(). To avoid memory leaks, I want to keep track of these allocations and de-allocate all of them on the destruction of the DLL.
Is there any way to write a function that will be called when my DLL is unloaded?
One thing I can think of is creating a global object in my DLL and writing the memory free calls in its destructor, but this seems like overkill.
My other idea is to just rely on the operating system to free the memory when the DLL unloads, but this seems dirty.
Is there any way to write a function that will be called when my DLL is unloaded? One thing I can think of is creating a global object in my DLL and writing the memory free calls in its destructor
That's possible, although I believe exactly when your object's destructor will be called will be undefined.
You might be interested in DLL_PROCESS_DETACH, and although you should avoid doing anything significant in DllMain, it seems deallocating resources is acceptable here. Note the caveats:
When a DLL is unloaded from a process as a result of an unsuccessful load of the DLL, termination of the process, or a call to FreeLibrary, the system does not call the DLL's entry-point function with the DLL_THREAD_DETACH value for the individual threads of the process. The DLL is only sent a DLL_PROCESS_DETACH notification. DLLs can take this opportunity to clean up all resources for all threads known to the DLL.
When handling DLL_PROCESS_DETACH, a DLL should free resources such as heap memory only if the DLL is being unloaded dynamically (the lpReserved parameter is NULL). If the process is terminating (the lpvReserved parameter is non-NULL), all threads in the process except the current thread either have exited already or have been explicitly terminated by a call to the ExitProcess function, which might leave some process resources such as heaps in an inconsistent state. In this case, it is not safe for the DLL to clean up the resources. Instead, the DLL should allow the operating system to reclaim the memory.
You might need to elaborate on why your DLL can hold on to memory, if you have numerous objects created by the DLL, they should have a defined lifecycle and clean themselves up at the end of their life.
If they're not objects (i.e. memory being allocated and returned to the caller via functions) why not put the responsibility back onto whoever is consuming your DLL? They can free the memory. The Terminal Services library follows this pattern (WTSFreeMemory).
If the resources are long-lived and must exist for the lifetime of your library, let the consumer control the lifecycle of your library. Write two functions: MyFrameworkStartup and MyFrameworkShutdown as appropriate. Winsock follows this pattern (WSAStartup and WSACleanup).
My other idea is to just rely on the operating system to free the memory when the DLL unloads, but this seems dirty.
You'll be okay if the process is exiting:
Don't worry about freeing memory; it will all go away when the process address space is destroyed. Don't worry about closing handles; handles are closed automatically when the process handle table is destroyed. Don't try to call into other DLLs, because those other DLLs may already have received their DLL_PROCESS_DETACH notifications, in which case they may behave erratically in the same way that a Delphi object behaves erratically if you try to use it after its destructor has run.
Make sure you read the whole article and comments and understand it before implementing the "do nothing" strategy.
How/when is the memory allocated? Usually, the sanest option is to try to preserve some kind of symmetry (constructor allocates, destructor deallocates. Or memory allocated when DLL is loaded, and freed when DLL is unloaded).
In any case, if you want to be notified when the DLL is unloaded, look into the DllMain function, and specifically the DLL_PROCESS_DETACH parameter.
The DllMain function is called, with fdwReason set to DLL_PROCESS_DETACH, when a DLL is unloaded. As described in the documentation, make sure you check the value of lpvReserved and only free memory if it is NULL; you should not free memory if the process is terminating.
For example, in language X:
let x = CreateOject( "MyProgID" )
x.LateBoundCall()
x.Release() // (or setting x to Nothing in VB-like language, etc)
What happens to the DLL MyProgID lives in? Does COM unload DLLs automatically?
EDIT
This is assuming that the code above is in an executable that does not expose any COM.
Yes, but not in a deterministic way. Windows periodically asks every loaded DLL "is it safe to unload you now?" Any DLL that responds "Yes" is unloaded.
Note a remark from MSDN :
If a DLL loaded through a call to
CoGetClassObject fails to export
DllCanUnloadNow, the DLL will not be
unloaded until the application calls
the CoUninitialize function to release
the OLE libraries.
See this Old New Thing article.
you have to manually release the resources used by COM objects. they use a ref counter internally to keep the number of references to the component. if the component still has a refcounter > 0, then the dll will not unload and the resources will not be freed.
Let's say I write a DLL in C++, and declare a global object of a class with a non-trivial destructor. Will the destructor be called when the DLL is unloaded?
In a Windows C++ DLL, all global objects (including static members of classes) will be constructed just before the calling of the DllMain with DLL_PROCESS_ATTACH, and they will be destroyed just after the call of the DllMain with DLL_PROCESS_DETACH.
Now, you must consider three problems:
0 - Of course, global non-const objects are evil (but you already know that, so I'll avoid mentionning multithreading, locks, god-objects, etc.)
1 - The order of construction of objects or different compilation units (i.e. CPP files) is not guaranteed, so you can't hope the object A will be constructed before B if the two objects are instanciated in two different CPPs. This is important if B depends on A. The solution is to move all global objects in the same CPP file, as inside the same compilation unit, the order of instanciation of the objects will be the order of construction (and the inverse of the order of destruction)
2 - There are things that are forbidden to do in the DllMain. Those things are probably forbidden, too, in the constructors. So avoid locking something. See Raymond Chen's excellent blog on the subject:
Some reasons not to do anything scary in your DllMain
Another reason not to do anything scary in your DllMain: Inadvertent deadlock
Some reasons not to do anything scary in your DllMain, part 3
In this case, lazy initialization could be interesting: The classes remain in an "un-initialized" state (internal pointers are NULL, booleans are false, whatever) until you call one of their methods, at which point they'll initialize themselves. If you use those objects inside the main (or one of the main's descendant functions), you'll be ok because they will be called after execution of DllMain.
3 - Of course, if some global objects in DLL A depend on global objects in DLL B, you should be very very careful about DLL loading order, and thus dependancies. In this case, DLLs with direct or indirect circular dependancies will cause you an insane amount of headaches. The best solution is to break the circular dependancies.
P.S.: Note that in C++, constructor can throw, and you don't want an exception in the middle of a DLL loading, so be sure your global objects won't be using exception without a very, very good reason. As correctly written destructors are not authorized to throw, the DLL unloading should be ok in this case.
This page from Microsoft goes into the details of DLL initialization and destruction of globals:
http://msdn.microsoft.com/en-us/library/988ye33t.aspx
If you want to see the actual code that gets executed when linking a .dll, take a look at %ProgramFiles%\Visual Studio 8\vc\crt\src\dllcrt0.c.
From inspection, destructors will be called via _cexit() when the internal reference count maintained by the dll CRT hits zero.
It should be called when either the application ends or the DLL is unloaded, whichever comes first. Note that this is somewhat dependent on the actual runtime you're compiling against.
Also, beware non-trivial destructors as there are both timing and ordering issues. Your DLL may be unloaded after a DLL your destructor relies on, which would obviously cause issues.
In windows binary image files with extension *.exe, *.dll are in PE format
Such files have Entry Point. You can view it with dumpbin tool like
dumpbin /headers dllname.dll
If you use C runtime from Microsoft, then your entry point will be something like
*CRTStartup or *DllMainCRTStartup
Such functions perform initialization of c and c++ runtime and delegate execution to (main, WinMain) or to DllMain respectively.
If you use Microsofts VC compiler then you can watch at source code of this functions in yours VC directory:
crt0.c
dllcrt0.c
DllMainCRTStartup process all things need to init/deinit your global variables from .data sections in normal scenario, when it retrive notification DLL_PROCESS_DETACH during dll unload. For example:
main or WinMain of startup thread of program returns control flow
you explictly call FreeLibrary and use-dll-counter is zero
When DllMain with fdwReason = DLL_PROCESS_DETACH parameter is called it means the DLL is unloaded by the application. This is the time before the destructor of global/static objects gets called.