tags:

views:

217

answers:

3

Hello all.

Here is my problem. I'm making C++ dll, which extensively relies on instance object exports. So i return my actual instances as a pointers to interface through some exported factory method.

Interfaces i use are purely virtual, to avoid linking problame. So i need a pure virtual destructor too, and i implemented one (with empty body, as i googled it). All compiles perfectly well, except... I can't see, if the actual destructors are called or not - because when i added some

std::cout << "hello destructor";
i never get to see it.

I have some explicit "delete obj" (EDIT: and it's called from "FreeObject" method inside the dll), that's not the problem.

Am i missing something? Is there another way to delete my object through interface?

EDIT: Again, i don't have memory management inconsistency, it's all inside dll. But right destructor just don't start.

+2  A: 

You shouldn't mix and match calls to new and delete across DLL boundaries.

Instead, I'd recommend the tried-and-true method that COM uses: AddRef and Release. When the reference count hits zero, Release calls delete this; from inside the DLL, ensuring that new and delete are matched.

Ben Voigt
Already took care about this.I have edited my question to be clear.
ALOR
I still recommend using the COM AddRef/Release pattern. `FreeObject` sounds like an awfully generic name, how is the parameter defined? The pointer deleted has to have a compile-time type at least as specific as the base class that declares the virtual destructor in order for virtual deletion to happen -- `delete (void*)p` will never call any destructor on `p`.
Ben Voigt
The use of new/delete across dll bun dries was a problem 10 years ago when the runtime was only available as a static library. This problem was solved with the introduction of the shared lib version of the runtime dll (which means there is a single heap for the whole application). Unless you are "manually" loading/unloading dll's the use of new/delete across dll bun dries is no longer a problem.
Martin York
Ben Voigt, thanks to you, i've finally understood where is my problem and how to solve it.It's really "awfully generic" method, and that prevented it from doing it's job. Stupid of me ( I've went to the COM pattern and it works perfectly well. Thx.
ALOR
@ALOR: Glad to help. @Martin: You have some animosity against the word "boundaries", or just ran out of space? Anyway, the COM pattern allows the caller and implementer to use different compilers, even different languages. Sharing a run-time DLL just results in extreme fragility, as no piece can be ported to a new compiler version until all of them are. This kind of coupling is something good software engineers strive to avoid.
Ben Voigt
A: 

You don't need destructor in the interface at all. Proper destructor must be seen only by delete caller. Outside the DLL, use an interface pointer as a handle, not something you can create / destroy. Object construction / destruction should be be inside the DLL. You can use reference counting or any other technique you want, just provide proper exports to access and manipulate objects, you decide how much memory management will be encapsulated.

adf88
+1  A: 

This is how I solved your particular problem for dynamically loaded C++ classes -

Have a base class for all pluggable objects, ie

class object_t {

 public:
  virtual ~object_t();

 //other type utils...

};

Have an base interface for all plugin interfaces, ie

class object_t;

class interface_t {

 public:
  virtual object_t* object() = 0;

}

object_t will have linkage, define it in its own dll that you will link against plugin classes. Other useful hooks to have in object_t are copying, spawning, RTTI and other type utils, my base object has spawn(), copy(), object_name() for example.

So all concrete classes derive from object_t and their respective pure virtual interface type, and all published (pluggable) interfaces derive from interface_t.

Then you can load a plugin, instantiate the interface using your factory and delete thusly -

delete interface->object()

And as object_t has a virtual destructor the correct destructor will be called.

Theres no problem with where you delete the object under linux, its fine under window's if all plugins/executables are linked against the same dynamic (dll) CRT.

Hayman
The very term "dll" implies Windows, on Linux he'd say "so" (shared object). Furthermore, all binaries being linked against the same CRT is a very difficult requirement to meet over the long haul. Imagine if you wanted to write a Explorer context-menu plugin and Microsoft said "for backward compatibility with old plugins we're still compiling with Visual C++ 4.0, you have to as well, so forget about using exceptions, templates, or any other modern C++ feature in your plugin".
Ben Voigt