Передача boost :: ptr_list из библиотеки клиенту

Я динамически загружаю библиотеку на C ++, как описано здесь.

Мой абстрактный базовый класс выглядит так:

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

И моя библиотека теперь предоставляет производный класс 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));
}

и create и destroy функции

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

Моя клиентская программа загружает библиотеку и две функции create и destroy. Затем он создает экземпляр Derived и использует его:

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

Теперь моя проблема: когда список заполняется библиотекой, вызывается new библиотеки для создания AnotherObjects. С другой стороны, когда список уничтожается, вызывается delete клиента для уничтожения AnotherObject. Что я могу сделать, чтобы избежать этой проблемы?


person phlipsy    schedule 15.07.2009    source источник


Ответы (3)


  1. Используйте std::list<shared_ptr<AnotherObject> >.
  2. Передайте собственное средство удаления в shared_ptr, которое вызывает правильное удаление.
person rpg    schedule 15.07.2009
comment
Это часть системы плагинов. В каждой библиотеке, вероятно, есть свои новые / удаляемые. Кроме того, я хочу собрать все мои объекты AnotherObject в глобальном списке клиентов. Таким образом, мне также нужно собрать все удалители ... - person phlipsy; 15.07.2009
comment
Шаг 2 выполнять не нужно. Просто используйте shared_ptr. Он волшебным образом знает, к какому delete позвонить. - person Kirill V. Lyadvinsky; 15.07.2009
comment
В exe должен быть только один удалитель, клиентские dll не будут знать, как удаляется память. Идея состоит в том, чтобы создать все объекты внутри вашего основного исполняемого файла и передать как средство удаления shared_ptr функцию, которая вызывает удаление из библиотеки cpp вашего exe. - person rpg; 16.07.2009
comment
Но библиотеки должны создавать свои новые объекты, потому что их знает только библиотека. Я не могу написать новый NewLibraryObject в своем клиенте. Клиент знает только базовый класс абстрактного интерфейса. - person phlipsy; 16.07.2009
comment
Наконец я выбрал именно это решение, и оно работает! Долгий путь ... Правильный ответ и проголосовали! - person phlipsy; 07.10.2009

Простой ответ - настоять на том, чтобы и приложение, и библиотека были скомпилированы с использованием одной и той же версии компилятора, и в этом случае они оба получат одинаковые новые / удаляемые версии.

person Community    schedule 15.07.2009
comment
Я предполагаю, что он заменил операторы new / delete в основной программе, но библиотека их не получает. - person AProgrammer; 15.07.2009
comment
Это часть системы плагинов. Таким образом, я должен каким-то образом гарантировать, что он не выйдет из строя, если кто-то другой с другой стандартной библиотекой напишет новый плагин. - person phlipsy; 15.07.2009
comment
Я не думаю, что это выполнимо. Если библиотека и приложение используют разные реализации STL (на данный момент игнорируя boost), то объект списка, возвращаемый из библиотеки, возможно, будет иметь реализацию, отличную от кода, который использует его в приложении, с предсказуемо плохими результатами. По сути, для такого рода вещей не существует бинарного стандарта. - person ; 15.07.2009
comment
О, верно. Я не учел этого. Поэтому я могу использовать только базовые языковые инструменты C ++. И сейчас? Каждая библиотека должна предоставлять несколько плагинов ... - person phlipsy; 16.07.2009
comment
Нет простого решения. Это как раз та проблема, для решения которой MS изобрела COM, но это не назовешь простым :-( - person ; 16.07.2009

Наилучший способ - иметь один оператор new и один оператор delete для всей программы. Есть параметры связывания, которые могут помочь (я помню -Wl, - export-dynamic, но это может быть связано с другой, но связанной проблемой).

Если это невозможно, убедитесь, что все операции удаления выполняются той же сущностью, которая делает новое, поэтому не определяйте их во встроенных функциях.

person AProgrammer    schedule 15.07.2009