Using Paul Nettle's Mem Manager Inside a DLL

Started by
2 comments, last by btaraman 17 years ago
Hello everyone, I am using Paul Nettle's Memory Manager inside a DLL. I found out that it works fine to find memory leaks inside the DLL, but it doesn't detect leaks in an executable linked to this DLL (even with the Memory Manager header enabled). Has anyone faced the same problem and found a clean solution for it?
Advertisement
If the client of the DLL uses malloc/free or new/delete, it will use the native memory manager of the client application, not the DLL. The way to change this would be to call your own new/delete allocators which, under the cover, use the DLL's allocators & memory manager. I can't think of a way a DLL can hook the allocator of the client code unless the client was compiled to take advantage of a different allocation system than just raw new/delete.

Does that make sense?

You could use something like this:

// Define abstract interface to an allocatorclass IAllocator{public:virtual void* Allocate( size_t size ) = 0;virtual void  Deallocate( void* address ) = 0;};extern IAllocator* GetAllocator();// Define macros to use it#define MYNEW(x) reintepret_cast<x*>(GetAllocator()->Allocate(sizeof(x)))#define MYDELETE(x) GetAllocator()->Deallocate(x)// Use MYNEW and MYDELETE everywhere, and/or overload new and delete// ie:Teapot* pTeapot = MYNEW(Teapot);// Create a default implementation of the alocatorclass DefaultAllocator : public IAllocator{public:virtual void* Allocate( size_t size ) { return malloc( size ); }virtual void  Deallocate( void* address ) { free( address ); }};// In your DLL create your own allocatorclass PaulNettleAllocator : public IAllocator{public:virtual void* Allocate( size_t size ) { return PaulNettleMalloc( size ); }virtual void  Deallocate( void* address ) { PaulNettleFree( address ); }};// In your application that hosts the DLL declare the default & global allocatorstatic DefaultAllocator theDefaultAllocator;IAllocator* s_pCurrentAllocator = &theDefaultAllocator;IAllocator* GetAllocator() { return s_pCurrentAllocator; }// Add some extra functions for setting a new allocatorIAllocator* SetNewAllocator( IAllocator* pAllocator ){IAllocator* pOldAllocator = pCurrentAllocator ;pCurrentAllocator  = pAllocator;return pOldAllocator;};


Now, when you DLL starts up, have it call SetNewAllocator() with it's PaulNettle allocator and save the old allocator returned. When it unloads have it restore the old allocator. You could instead use a stack so the DLL just pops its allocator and the host application can keep track of the allocators.


This is similiar to how we've done some of our console work.

Hope that helps/makes sense??


Hey Sphet!

Yes, that does make sense. Look, it will take a while for me to give it a try. I will let you know when I do. Thanks for the help!

Cheers!
Hey Sphet!

Thanks for the hint man. Actually, I got that working! I didn't implement a stack, but a list of modules that are hooked to the memory manager. I didn't test all of it yet, but I am afraid that DLLs that use the memory manager that is inside the main DLL may be loaded/unloaded not in FIFO order, especially those that are loaded dynamically. All of this gave me a better understanding of memory management.

One small detail of how I implemented it: I created a .inl file that has the bodies of the allocators and a static instance of a class that puts/removes the current module in the list of modules currently hooked to the memory manager opon its construction/destruction. This .inl file is to be included once in every module where memory manager is to be used. I liked this solution and so far I see no downside in it. Having you used a similar system in consoles, I would like to know if you see any problem in using this approach?

Thanks!

This topic is closed to new replies.

Advertisement