# Deallocation of DLL-allocated objects

## Recommended Posts

Trillian    410
Hello! I have a pretty simple question. You know these IUnknown base interfaces used by DirectX (all COM?), IrrLicht and many libraries? I know those are used to ensure that deallocation of the object is done in proper memory space (and ref counting also). But I have a question regarding the implementation : My engine consists of a couple of .libs which might eventually be compiled into .dlls. Thus, I have created a base "Unknown" class which is defined in my "core" library (statically-linked). I want to know where must the "delete this;" code must be placed in order to respect the correct memory space stuff. 1- It could be inlined into the header of Unknown::selfDestroy(), but I don't think this is okay. 2- It could be defined in the .cpp implementation of Unknown::selfDestroy(), but then is the code deleting from the app or the dll? (unknown.cpp is in a statically linked library but derived classes might be in dlls) 3- It could be implemented into each and every of the Unknown-derived classes .cpp files. So, where must this be placed? Also, I'd like to know if linux's Shared Objects share the same rules.

##### Share on other sites
ldeej    308
The internal mechanics of COM are fairly complex, hard to explain on a single post.

I had not looked at it for a while (there is a good book that explains it fairly well, I believe is Inside COM), but you certainly want the implementation on the .cpp, you do not want it inlined unless you use a secondary memory management layer for it (not just new/delete)

Note that the COM system allocates the memory for you (CoCreateInstance), and it also releases it. You need to provide this on your Unknown code base to make sure that destruction works as expected.

##### Share on other sites
Trillian    410
I do not want to use COM, but to create a similar Unknown base class to use in my engine.

I just thought about that, it should be okay if the statically-linked core library contains the implementation (the "delete this;"), because anyways the dlls will link to this library, so the code of the core library will be integrated into the dll, thus the dlls will be calling the "delete this" into their own memory space, and it will work correctly... does that make any sense?

##### Share on other sites
Sneftel    1788
I don't think you entirely understand the reason for not calling delete from the app. Both the app and the DLL run in the _same_ memory space. However, they may use different systems for heap allocation. Because of this, it's important that if a piece of memory is heap-allocated with the DLL's allocation function it needs to be deallocated with the DLL's deallocation function, and vice versa if it was allocated with the app's allocation function. The COM approach, and the one you're using, is to have all of that be DLL-side. In order for this to happen, you just need to make sure that any new and delete calls on library objects are happening in a .cpp file which was compiled with the library.

EDIT: actually, after rereading your last message I have no idea whether you already knew that. Sooo... HTH. [grin]

##### Share on other sites
ldeej    308
I understand that you do not want to use COM, my point is that to achieve this behavior COM has to go through lots of tedious details, and that the book I suggested explains COM on the first few chapters from the point of view of what you are trying to do.

What you describe makes sense as long as dll boundaries are not crossed, you do not want to call delete on the wrong memory manager.

Here is the problem that I think could be found with your approach:

my_physics_dll uses unknown and exposes physics : unknown
my_graphics_dll uses unknown and exposes graphics : unknown

If you create an object on my_physics_dll (Create/AddRef) and delete it (Release) on my_graphics.dll by casting it to unknown you can end up calling the wrong memory manager (unless unknown is pure abstract)

Note also that as long as IUnknown is a pure abstract class then you should be fine since you are exposing only the interface and not the implementation.

Does it make sense?

##### Share on other sites
Trillian    410
Quote:
 Original post by ldeejDoes it make sense?

It does. That was clear, it answers my question. I will make Unknown pure virtual.... here, I'll toss a random implementation:

class Unknown{private:  unsigned int m_RefCount;protected:  virtual ~Unknown() {}  virtual void selfDestroy() = 0; // Implementation { delete this; } in derived classes.public:  inline Unknown() : m_RefCount(0) {}  inline void grab() { ++m_RefCount; }  inline void drop() { if(--m_RefCount == 0) selfDestroy(); }  inline unsigned int getRefCount() const { return m_RefCount; }};

Is this implementation okay? Is it ready to be used for my dll stuff?

Thanks

##### Share on other sites
Sneftel    1788
There's no reason to make selfDestroy virtual, as long as the destructor is virtual.

##### Share on other sites
Trillian    410
Quote:
 Original post by SneftelThere's no reason to make selfDestroy virtual, as long as the destructor is virtual.

Thanks. I'll fix that. I'll inline it like the other functions.

##### Share on other sites
ldeej    308
SelfDestroy needs to be virtual to make sure the destruction respects memory allocations across dll boundaries.

This is only half the equation and this is the easy part, the hard part is allocating objects. What do you have in mind for that.

##### Share on other sites
Sneftel    1788
Quote:
 Original post by ldeejSelfDestroy needs to be virtual to make sure the destruction respects memory allocations across dll boundaries.

Ohh, I see. You're putting the base class and the derived class in different DLLs. In that case you're right about the virtual (though if it were me, I'd put the allocation and deallocation both in the Unknown class, via a custom allocation function).

Actually... hmm. I don't think it would need to be virtual even then, since the compiler pastes the memory deallocation onto the destructor code rather than at the callsite of the destructor.

##### Share on other sites
Jansic    251
Quote:
 Actually... hmm. I don't think it would need to be virtual even then, since the compiler pastes the memory deallocation onto the destructor code rather than at the callsite of the destructor.

I'm fairly certain this is incorrect since forced calls to destructors "object->~object()" don't result in memory being freed. In fact the whole point of the original question was to prevent the memory manager of one module going looking for an object pointer from another module, if this mechanism worked then we'd never need to bother.

Jans.

##### Share on other sites
Sneftel    1788
BTW, what sort of an environment are you expecting to use this in? If you're planning to use this interface between different compilers, none of this will work because of ABI incompatibilities. And if you're doing it all on one compiler, as long as you use a DLL-compatible runtime (as is default for recent visual studio versions) there's nothing to worry about at all and you don't need special deletion functions.

##### Share on other sites
Trillian    410
Now I'm getting a bit confused here. Let me make myself clear :

CORE - Static Library, constains the base "Unknown" class.
FOOBAR - Dynamic library, links to CORE and derives it's classes from CORE'S "Unknown" class.
GAME - Application, links to CORE and uses FOOBAR.

Now, if the "delete this;" are inlined into CORE, when FOOBAR will compile, the "delete this;" code will be pasted into the FOOBAR dll. As such, it will be the foobar itself deleting it's own allocated memory, and that'd work...

No.

Writing this I saw the problem : even if FOOBAR can deallocate it's own memory correctly, the GAME linking to CORE will inline the "delete this;" and delete the FOOBAR objects as if it was in the GAME's memory thing.

So I need to use pure virtuals.

##### Share on other sites
Jansic    251
The easiest solution to this is to make your base class pure and force the reference counting in at instantiation time, like this:

// Pure baseclass Unknown{public:    virtual void grab()=0;    virtual void drop()=0;};// Your classclass MyClass : Unknown{    // MyClass stuff, but do not implement Unknown};// Instantiation wrappertemplate <typename BASE>class Dynamic : public BASE{    int m_iRefCount;public:    Dynamic() { m_iRefCount = 0; }    void grab() { m_iRefCount++; }    void drop() { if ( --m_iRefCount == 0 ) delete this; }};

So... in the DLL that _provides_ these objects you can instantiate the object as follows:

MyClass *CreateMyClass()  // Example only - returning refcounted objects like this is bad form.{    MyClass *pMyClass = new Dynamic<MyClass>();    pMyClass->grab();    return pMyClass;  }

This has the hidden benefit that if MyClass multiply inherits 'unknown' through two different paths, it all still works...

Jans.

##### Share on other sites
ldeej    308
No, it would not work if you inherit from Unknown from different parents, the call will be ambiguous.

EDIT: Unless you use virtual inheritance for Unknown obviously :-)

##### Share on other sites
eq    654
This is what I use for most of classes (apart from very simple one's):
// .h fileclass MyClass{public:   static MyClass* create();   void release();protected:// Make sure that the only way to create and destroy the object is by using the create/release pair.   MyClass();   ~MyClass();};// .cpp fileMyClass*MyClass::create(){   return new MyClass;}voidMyClass::release(){   delete this;}

This makes sure that the object can only be alloacted and deallocated within the same compilation unit.
Done it in this way for years now (very often using DLL's) without any problems.

If you want to add ref counting, com style intefaces on top of that, it's up to you.
But to make sure that a class can be used with DLL's the above seems to be enough.

##### Share on other sites
Trillian    410

// Unknown.hppclass Unknown{private:  int m_RefCount;  inline Unknown() : m_RefCount(0) {} // Private constructor  virtual ~Unknown() {} // Private destructorprotected:  virtual selfDestroy() = 0;public:  inline void grab() { ++m_RefCount; }  inline void drop() { if(--m_RefCount <= 0) selfDestroy(); }  inline int getRefCount() const { return m_RefCount; }  template<class> friend class UnknownBase; // Whatever the syntax for this is};template<class T>class UnknownBase : virtual public Unknown{protected:  inline UnknownBase() {} // Protected constructor  virtual ~UnknownBase() {} // Protected destructorpublic:  static T * Create();};

And then :

// Derived.hppclass Derived : public UnknownBase<Derived>{protected:  virtual void selfDestroy();};// Derived.cppDerived * UnknownBase<Derived>::Create() { return new Derived(); }void Derived::selfDestroy() { delete this; }

This solves the problems of :
- Mandatory allocation via a common static function (must derive from UnknownBase because Unknown's constructor is private)
- Deallocation via a virtual function
- Reference counting in base class
- Mandatory virtual inheritance from Unknown because of mandatory inheritance from UnknownBase

Is there any problem with this approach?

[Edited by - Trillian on May 12, 2007 7:04:26 AM]

##### Share on other sites
Jansic    251
Quote:
 Original post by ldeejNo, it would not work if you inherit from Unknown from different parents, the call will be ambiguous.EDIT: Unless you use virtual inheritance for Unknown obviously :-)

I was taking the requirement for virtual inheritance as read.

Jans.