views:

1333

answers:

7

Consider this case:

dll = LoadDLL()
dll->do()

...
void do() {
    char *a = malloc(1024);
}
...

UnloadDLL(dll);

At this point, will the 1k allocated in the call to malloc() be available to the host process again? The DLL is statically linking to the CRT.

+1  A: 

No, you do not leak.

If you mix dll models (static, dynamic) then you can end up with a memory error if you allocate memory in a dll, that you free in a different one (or freed in the exe)

This means that the heap created by the statically-linked CRT is not the same heap as a different dll's CRT.

If you'd linked with the dynamic version of the CRT, then you'd have a leak as the heap is shared amongst all dynamically-linked CRTs. It means you should always design your apps to use the dynamic CRTs, or ensure you never manage memory across a dll boundary (ie if you allocate memory in a dll, always provide a routine to free it in the same dll)

gbjbaanb
Thank you!Could you elaborate on how/when the CRT deallocates its heap storage? Is this added as some sort of default dll exit code by the compiler/linker?
Viktor
WARNING: Implemention-dependent! A CRT may simply provide access to the OS heap for a process, in which case you *can* allocate in a DLL and free outside.
MSalters
DllMain will be called at exit. I expect it reference counts until the dll is completely unloaded,and removes the heap then. MSalters is right, eg you can allocate anywhere and free anywhere, but if your app crashes, you leak memory that nothing short of a reboot can free (eg Win3.1 global heap)
gbjbaanb
+1  A: 

One could do a test and see if there are memory leaks. You run a simple test 30 times allocating 1 MB each time. You should figure that out quite quickly.

One thing is for sure. If you allocated memory in the DLL you should also free that memory there (in the DLL).

For example you should have something like this (simple but intuitive pseudocode):

dll = DllLoad();

ptr = dll->alloc();

dll->free(ptr);

DllUnload(dll);

This must be done because the DLL has a different heap than the original process (that loads the dll).

Iulian Şerbănoiu
+1  A: 

From MSDN Potential Errors Passing CRT Objects Across DLL Boundaries

Each copy of the CRT library has a separate and distinct state. As such, CRT objects such as file handles, environment variables, and locales are only valid for the copy of the CRT where these objects are allocated or set. When a DLL and its users use different copies of the CRT library, you cannot pass these CRT objects across the DLL boundary and expect them to be picked up correctly on the other side.

Also, because each copy of the CRT library has its own heap manager, allocating memory in one CRT library and passing the pointer across a DLL boundary to be freed by a different copy of the CRT library is a potential cause for heap corruption.

Hope this helps.

kervin
+4  A: 

You can't tell. This depends on the implementation of your static and dynamic CRT. It may even depend on the size of the allocation, as there are CRTs that forward large allocations to the OS, but implement their own heap for small allocations.

The problem with a CRT that leaks is of course that it leaks. The problem with a CRT that does not leak is that the executable might reasonable expect to use the memory, as malloc'ed memory should remain usable until free is called.

MSalters
+4  A: 
  1. Memory used by a process as tracked by the OS is applicable to the full process and not specific to a DLL.

  2. Memory is given to the program in chunks by the OS, called heaps

  3. The heap managers (malloc / new etc) further divide up the chunks and hands it out to requesting code.

  4. Only when a new heap is allocated does the OS detect an increase in memory.

  5. When a DLL is statically linked to the C Run time library (CRT), a private copy of CRT with the CRT functions that the DLL's code invokes is compiled and put into the DLL's binary. Malloc is also inclued in this.

  6. This private copy of malloc will be invoked whenever the code present inside the statically linked DLL tries to allocate memory.

  7. Consequently, a private heap visible only to this copy of malloc, is acquired from the OS by this malloc and it allocates the memory requested by the code within this private heap.

  8. When the DLL unloads, it unloads its private heap, and this leak goes unnoticed as the entire heap is returned back to the OS.

  9. However If the DLL is dynamically linked, the memory is allocated by a single shared version of malloc, global to all code that is linked in the shared mode.

  10. Memory allocated by this global malloc, comes out of a heap which is also the heap used for all other code that is linked in the dynamic aka shared mode and hence is common. Any leaks from this heap therefore becomes a leak which affects the whole process.

Edit - Added descriptions of the linking scenario.

A: 

I don't know.. I'm looking a case where the DLL allocates (via dynamically linked malloc) both small and large memory chunks. After the DLL unloads, the small allocations are still there but the large allocation disappears. I went into this assuming all dynamically allocated memory from a shared library would be tied to the process and not the module (i.e. DLL), but I was wrong.. anybody know how I can change this?

A: 

Actually, the marked answer is incorrect. That right there is a leak. While it is technically feasible for each dll to implement its own heap, and free it on shutdown, most "runtime" heaps - static or dynamic - are wrappers around the Win32 process heap API.

Unless one has taken specific care to guarantee that this is not the case, the dll will leak the allocation per load,do,unload cycle.

Chris Becke