Note: It is important to realize that a single address space consists of one executable module and several DLL modules. Some of these modules can link to a static version of the C/ C++ run-time library, some of these modules might link to a DLL version of the C/C++ run-time library, and some of these modules (if not written in C/C++) might not require the C/ C++ run-time library at all. Many developers make a common mistake because they forget that several C/C++ run-time libraries can be present in a single address space. Examine the following code:
VOID EXEFunc() {
PVOID pv = DLLFunc();
// Access the storage pointed to by pv...
// Assumes that pv is in EXE's C/C++ run-time heap
free(pv);
}
So, what do you think? Does the preceding code work correctly? Is the block allocated by the DLL's function freed by the EXE's function? The answer is: maybe. The code shown does not give you enough information. If both the EXE and the DLL link to the DLL C/C++ run-time library, the code works just fine. However, if one or both of the modules link to the static C/C++ run-time library, the call to free fails. I have seen developers write code similar to this too many times, and it has burned them all.
At first one thing the starup() function do is to initialize a heap used by malloc and free and low-level IO manipulation use in CRT, so when there is two copies CRT liberary in one process adress and there will be two heaps for two groups of malloc and free, and that one block memory grabed by malloc can only be freed by the very free() function in the same copy.
every malloc()function return pointer to a block,however there are some bytes ahead the block conserved for system information, and this information is stored in a struct mem_control_block, so indeed the pointer malloc()function returned points to the byte after the mem_control_block.
struct mem_control_block {
int is_available; //a flag that specify whether this block can be used by any other application
int size; //the size of the block
};
finnally, it seems no error in these code:
VOID EXEFunc() {
PVOID pv = DLLFunc();
// Access the storage pointed to by pv...
// Assumes that pv is in EXE's C/C++ run-time heap
free(pv);
}
And to answer your question about DLL and local heap. This time I mean the heap
Win16 dll could and usually had a local heap in local sense and that one was mapped into the global memory space and then dll was used system wide. Memory management simply required to create and destroy object from dll because memory management was such that exe did not know about the position of a dll memory in the global space. It was just using it. The memory management was never constructed to support sharing a heap unless specified that memory block is such.
Win32 is mapping each dll into one and the same process space. So we should not have a problem with asking a memory from dll giving it to dll deleting new-ing, whatever. Right? Alas, we are sure that this is true only if we use system allocator functions properly. They do everything as it should be done and we have no problem with pointers from and to dll's as long as the same allocators are used which might not be the case if the system libraries are different. The problem is that some dll's have kept "old" or somehow adjusted memory managers that know nothing about Win32 sharing capabilities. They behave as if we are still dealing with Win16.
I would not be surprised at all, and I have met them, such compilers and C implementations of free, maloc, new and delete even today.
And the problem is of course if different dll's use different allocators.
Even under Win32, a dll still has its own local heap, it is just accessible from the main process. If you would do this: load dll, create some object on its heap, save the pointer in exe, unload dll, you would not be able to delete that object any longer, the pointer you have is invalid: no dll - no local heap.
Still this behavior asks for attention. You may have a static member pointer in a dll. You create an object and save the pointer into the static member variable. You go to another dll and ask for the static member pointer and nothing... though the space is shared and every heap accessible, the space of static members can be separated.
And this all picky details together create very difficult situation during development. If different teams have to use the same classes over several dll's and the application has a heavy pointer usage - watch out !
All in all you have to know what memory manager you use to be certain.