views:

148

answers:

3

I dynamically load a library in C++ like described here.

My abstract base class looks like this:

#include <boost/ptr_container/ptr_list.hpp>
class Base {
public:
    virtual void get_list(boost::ptr_list<AnotherObject>& list) const = 0;
};

And my library now provides a derived class Derived

class Derived : public Base { ... };

void Derived::get_list(boost::ptr_list<AnotherObject& list) const {
    list.push_back(new AnotherObject(1));
    list.push_back(new AnotherObject(2));
}

and create and destroy functions

extern "C" {
    Base* create() { new Derived; }
    destroy(Base* p) { delete p; }
}

My client program loads the library and the two create and destroy functions. Then it creates an instance of Derived and uses it:

Base* obj = create();
boost::ptr_list<AnotherObject> list;
obj->get_list(list);

Now my problem: When the list is filled by the library the library's new is called to create the AnotherObjects. On the other hand when the list is destroyed the client's delete is called for destroying the AnotherObjects. What can I do to avoid this problem?

A: 

The easy answer is to insist that both application and library are compiled with the same version of the compiler, in which case they will both get the same new/delete versions.

anon
I assume he has replaced the operators new/delete in the main program but the library doesn't get them.
AProgrammer
Well, he doesn't say anywhere that he has done that.
anon
It's part of an plugin system. Thus I have to guarantee somehow that it won't crash if someone else with an other standard library write a new plugin.
phlipsy
I don't think that is doable. If the library and the app use different STL implementations (ignoring boost for now) then list object coming back from the library will possibly have a different implementation from the code that uses it in the app, with predictably bad results. Basically, there is no binary standard for this sort of thing.
anon
Oh that's right. I didn't consider that. So I can only use the basic language tools of C++. And now? Each library should provide several plugins...
phlipsy
There is no simple solution. This is exactly the problem that MS invented COM to solve, but you couldn't call that simple :-(
anon
A: 

The best way is to have one operator new and one operator delete for the whole program. There are linking options which can help (I remember -Wl,--export-dynamic but it could be for a different but related problem).

If that isn't possible, ensure that all delete operation are made by the same entity which does the new, so don't define them in inline functions.

AProgrammer
+3  A: 
  1. Use a std::list<shared_ptr<AnotherObject> >.
  2. Pass a custom deleter to the shared_ptr that calls the proper delete.
rpg
It's part of a plugin system. Every library has probably its own new/delete. Besides I want to collect all my AnotherObjects in an client-global list. Thus I also have to collect all deleter...
phlipsy
You no need to perform step 2. Just use `shared_ptr`. It's "magically" knows which `delete` to call.
Kirill V. Lyadvinsky
There should be just one deleter in the exe, the client dlls won't know how the memory is deleted.The idea is to create all the objects inside your main exe and pass as shared_ptr's deleter a function that calls the delete from your exe's cpp lib.
rpg
But the libraries have to create their new objects because only the library knows them. I can't write "new NewLibraryObject" in my client. The client only knows the abstract interface base class.
phlipsy
Finally I choosed exact this solution and it works! A long way... Correct answer and voted up!
phlipsy
Glad to see that it worked :-)
rpg