C++ DLL Unload Destructor?

11,160

Solution 1

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.

Solution 2

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.

Solution 3

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.

Share:
11,160
Amil
Author by

Amil

Updated on June 14, 2022

Comments

  • Amil
    Amil almost 2 years

    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.

    Thanks

  • celtschk
    celtschk about 12 years
    According the link you gave, the standard DllMain provided by the runtime library calls the constructors/destructors of global objects. Therefore I guess just using a global object in the DLL with appropriate constructor/destructor should be sufficient.
  • Amil
    Amil about 12 years
    Thanks! This is perfect. Especially, the note about not needing to worry about freeing memory.
  • Amil
    Amil about 12 years
    Thanks for the nice and simple answer!
  • Amil
    Amil about 12 years
    Thanks for the response! The memory is allocated when the LPCSTR GetCSV() function is called. Basically, I am copying memory from a local std string into memory I allocate using GlobalAlloc() just to ensure that my caller has access to the memory after the function returns. I added some code to clean up memory from old calls to GetCSV() but I will not handle the final case of when the DLL is unloaded as this is apparently done automatically for me.