plugins - will this work?

Started by
10 comments, last by mago 18 years, 6 months ago
Hi I'm making my first application with plugins. I went through a lot of articles about this and only got more confused, but I came up with my own idea about how to do this. And it SEEMS to work. While working on my program, I want to ask somebody more experienced than me whether my design is really ok, or if there are memory leaks or something that I don't see... here it goes: The application consists of a "core" (the exe) and the plugins (DLLs). In the core, I define an abstract class
class CBase 
{
  private:
    CBase();
  public:
    virtual ~CBase() = 0;
    virtual void Method() = 0;
};
In each DLL, I define a CBase's derived class CDerived and a function
CBase* GetInstance()
{ 
  return (CBase*) new CDerived;
}
which is the only thing exported from the dll. The idea is that the exe will work with objects of type CBase, but those objects will really be instances of the derived classes. The exe will load each plugin and call GetInstance() to obtain an object pointer. I have already written the described program and it seems to work, but is it really ok? I mean for example when I do
CBase base = lpfnGetInstance();
delete base;
will the object get deallocated properly? I have read somewhere that the EXE and the DLL have different memory managers, so I don't know if it's ok to get an object pointer from the dll and call delete on it in the exe....? I repeat that this compiles correctly and does not produce any run-time errors, also Visual Leak Detector (from CodeProject) says that there are no memory leaks... thanks in advance for your opinions
thanx for sharing
Advertisement
When you allocate memory in a DLL you should really deallocate that memory in the same DLL. There are ways to get DLLs compiled with the same compiler to "work" with the executable, but that doesn't scale to plug-ins created by arbitrary compilers, which sort of defeats the entire purpose of making a plug-in aware program.

Also, if your Derived really is derived from CBase, then you don't need that cast.
Thanks for a quick answer.

You say I should deallocate the memory in the dll. Is it not enough that the CBase destructor is virtual? I thought that when I make the destructor virtual and call delete(CBase), then the destructor of CDerived (defined in the DLL) will be called instead (if the object is actually of class CDerived).

If not..

I really need the exe to control when the objects are destroyed, so the only thing that comes to my mind is to make a method like Destroy which will do the deleting.
Will at least one of the two ways described below work properly?


-------------------------
Approach nr.1:
class CBase{  public:    virtual ~CBase() = 0;    void Destroy() { delete this; };};class CDerived{  public:    ~CDerived();};


-------------------------
Approach nr.2:
class CBase{  public:    virtual ~CBase() = 0;    virtual void Destroy() = 0;};class CDerived{  public:    ~CDerived();    void Destroy() { delete this; };};

-------------------------


thank again for any help!

p.s. good point about the cast :)


thanx for sharing
When you delete an object two things actually happen. The first thing that happens is that the destructor gets called. The second thing is the memory is deallocated. If you delete the object via a base pointer and the destructor is virtual then the correct destructor for the object will be called. However, the second part of the equation, freeing the memory may not be happy. If the exe and dll maintain separate heaps, which is likely if the exe and dll are compiled with different compilers, then the exe will likely corrupt its own heap trying to free memory that wasn't allocated in the exe's heap.

It actually is even worse when you consider that the virtual destructor implementations may be different on different compilers or on the same compiler with different build settings. For example, since the dynamic size of an object is unknown when you call the destructor, but knowing the size is important when deallocating memory. Compiler A may embed the size in the vtable, compiler B might put that information as a header before the actual object in memory. So if compiler A tries to delete a class in a DLL created by compiler B, it may look in the vtable to get the size, but actually end up getting a function pointer which it interprets as a size. This number is most likely a lot bigger than the actual size. What may happen in this case is that the deallocation may actually corrupt both the heaps of the exe and the dll. Bad mojo.

In any case, I'd be highly suspicious about case number one, since that probably will invoke the wrong memory deallocation routine. Case number two looks like it'd probably work though.
Thanks! I finally understand what's going on there..
thanx for sharing
Ok, so I need to call the final "delete" on every object from the same DLL in which the object's class is defined.... the next thing that comes to my mind is to overload the "delete" operator in the base class to call the virtual function Destroy() that the derived class overloads.
This way, when I call "delete baseobjectpointer", it will call the Destroy() function in the derived class, defined in the DLL, and the memory will get released properly, right?
thanx for sharing
When operator delete gets called after the base class destructor gets called, the object's vptr is no longer valid, so calling a virtual function on the destructed object is probably not something that will work, and definately something that you shouldn't rely on.
SiCrane, thank you again for all your answers, it would take me days to figure this out on my own...

I didn't know that when you overload the delete operator, then the class's destructor still gets called before your code. This seems kind of a bad design to me, when I overload an operator, I expect to be able to change all of the its behavior, not just a half of it...

Well.. how do I do the plugin system then? I need to have one class per DLL and a common interface to access those classes.. (create object, call methods, destroy object).
thanx for sharing
Make the dll create the object instance when it gets loaded and make it delete it when it unloads. Then make your getinstance() method return the pointer to the object the dll holds.
cool...

how do I make the DLL do something on LoadLibrary() and FreeLibrary()? Did you mean that after I load the library I call a function defined in the dll and before I free it I call another function, or is there really a way to tell the dll to do stuff whene these events occur?

Also, I will need to create more than one instance of every class...
thanx for sharing

This topic is closed to new replies.

Advertisement