С++ Boost двоичная сериализация указателя, созданного из Boost object_pool

В моем приложении есть класс "MyClass". Его объекты создаются из Boost Object_pool.

Мне нужно сериализовать/десериализовать этот объект класса с помощью Boost Binary Serialization.

Для сериализации -

Я беру указатель из пула, делаю какие-то операции и сериализую его через бинарную сериализацию Boost. Пока все хорошо.

Для десериализации -

Я извлекаю этот сериализованный буфер и десериализую его с помощью двоичной сериализации Boost. Десериализация проходит успешно, но во время процесса новая память выделяется механизмом Boost Serialization, который не создан из пула объектов.
Если я выделяю указатель из пула до десериализации, десериализация выделяет память снова в куче и трек памяти из пула теряется. Следовательно, я не смогу повторно использовать эту память, выделенную механизмом ускоренной сериализации, поскольку ее нельзя вернуть в пул объектов, поскольку она не была создана из пула.

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/pool/object_pool.hpp>
#include <iostream>
#include <sstream>
#include <string>

class MyClass
{
  public :
    friend class boost::serialization::access;
    MyClass():data(9)
    {
      std::cout << std::endl << "MyClass()" << std::endl ;
    }

template<class Archive>
  void serialize(Archive & ar, const unsigned int version)
  {
    ar & data;
  }

~MyClass()
{
}

private :
  int data ;

};


int main()
{
  try
  {

    boost::object_pool<MyClass> pool ;

    // Get object from the Pool.
    MyClass *b = pool.construct();

    // Serialization

    std::stringbuf strbuf;
    boost::archive::binary_oarchive oa( strbuf ) ;
    oa << b ;

    // Deserilaiztion

    //MyClass *a = pool.construct() ;
    MyClass *a ;

    std::stringbuf strbufr(strbuf.str()) ; 
    boost::archive::binary_iarchive ia( strbufr ) ;

     // This calls the constructor and allocates memory for the pointer.
     // If we allocates this from the pool, new memory is still allocated     
     // and we loose track of the pointer fetched from the pool.   
     ia >> a;
  }
 catch ( boost::archive::archive_exception &e )
 {
   std::cout << std::endl << e.what() << std::endl ;
 }

}

Что мне нужно -

Я хочу десериализовать буфер в указатель, выделенный из пула.

Прошел через документ сериализации Boost и нашел концепцию оберток двоичных объектов, однако это приводит к ошибкам компиляции.

Основная функция : -

int main()
{
  try
  {

    boost::object_pool<MyClass> pool ;

    MyClass *b = pool.construct();

    std::stringbuf strbuf;
    boost::archive::binary_oarchive oa( strbuf ) ;
    oa << boost::serialization::binary_object(b, sizeof(MyClass) ) ;

    MyClass *a = pool.construct() ;

    std::stringbuf strbufr(strbuf.str()) ;
    boost::archive::binary_iarchive ia( strbufr ) ;

    ia >> boost::serialization::binary_object(b, sizeof(MyClass) );
  }
  catch ( boost::archive::archive_exception &e )
  {
    std::cout << std::endl << e.what() << std::endl ;
  }

}

Это дает следующие ошибки компиляции: -

serializationCpy.cpp: In function ‘int main()’:  
serializationCpy.cpp:56:8: error: no match for ‘operator>>’ (operand types are ‘boost::archive::binary_iarchive’ and ‘boost::serialization::binary_object’)
 ia >> boost::serialization::binary_object(b, sizeof(MyClass) );  
    ^
serializationCpy.cpp:56:8: note: candidate is:
In file included from /home/boost_root/include/boost/archive/detail/common_iarchive.hpp:23:0,
             from /home/boost_root/include/boost/archive/basic_binary_iarchive.hpp:30,
             from /home/boost_root/include/boost/archive/binary_iarchive_impl.hpp:21,
             from /home/boost_root/include/boost/archive/binary_iarchive.hpp:20,
             from serializationCpy.cpp:1:
/home/boost_root/include/boost/archive/detail/interface_iarchive.hpp:67:15: note: Archive& boost::archive::detail::interface_iarchive<Archive>::operator>>(T&) [with T = boost::serialization::binary_object; Archive = boost::archive::binary_iarchive]
 Archive & operator>>(T & t){
           ^
/home/boost_root/include/boost/archive/detail/interface_iarchive.hpp:67:15: note:   no known conversion for argument 1 from ‘boost::serialization::binary_object’ to ‘boost::serialization::binary_object&’  

Правильно ли использовать сериализацию с пулом объектов?
Мы будем очень признательны за помощь.


person Jerry    schedule 23.05.2018    source источник
comment
Я только что скомпилировал ваш код с помощью boost vc141 и 1.65.1 и вообще не получил ошибок компилятора.   -  person JHBonarius    schedule 23.05.2018
comment
Первая версия компилируется, это вторая основная функция, которая приводит к ошибкам компиляции. Я использую gcc 4.8.5 и boost 1.65.1, это дает мне ошибки компиляции.   -  person Jerry    schedule 23.05.2018


Ответы (2)


Источник из этого ответа, я думаю, что это должно быть

ia >> boost::serialization::make_binary_object(a, sizeof(MyClass));

or

ia & boost::serialization::make_binary_object(a, sizeof(MyClass));

вместо ia >> boost::serialization::binary_object(b, sizeof(MyClass) );

исправив другие опечатки, он станет:

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/binary_object.hpp>
#include <boost/pool/object_pool.hpp>
#include <iostream>
#include <sstream>

class MyClass
{
public:
    friend class boost::serialization::access;
    MyClass(int data) :data(data)
    {
        std::cout << "\nMyClass(" << data << ")\n";
    }

    MyClass()
    {
        std::cout << "\nMyClass()\n";
    }

    template<class Archive>
    void serialize(Archive & ar, const unsigned int version)
    {
        ar & data;
    }

    void printData()
    {
        std::cout << "Data = " << data << "\n";
    }
private:
    int data;
};

int main()
{
    try
    {
        boost::object_pool<MyClass> pool;

        MyClass *b = pool.construct(6);

        std::stringbuf strbuf;
        boost::archive::binary_oarchive oa(strbuf);
        oa << boost::serialization::binary_object(b, sizeof(MyClass));

        MyClass *a = pool.construct();

        std::stringbuf strbufr(strbuf.str());
        boost::archive::binary_iarchive ia(strbufr);

        ia >> boost::serialization::make_binary_object(a, sizeof(MyClass));

        a->printData();
    }
    catch (boost::archive::archive_exception &e)
    {
        std::cout << std::endl << e.what() << std::endl;
    }
    return 0;
}

вывод:

MyClass(6)

MyClass()
Data = 6

ДЕМО

person JHBonarius    schedule 23.05.2018
comment
Я понимаю, что make_binary_object возвращает const binary_object и теперь можно использовать его ссылку. Программа компилируется и все работает как надо. Однако ia & boost::serialization::binary_object(b, sizeof(MyClass)); не работает. - person Jerry; 23.05.2018
comment
@IranjeetSingh Что вы имеете в виду под не работает. Что он должен делать? Кстати, может быть b вместо a (объект, который вы только что создали перед ним) опечатка? А почему strbufr не используется? - person JHBonarius; 23.05.2018
comment
b вместо a была опечатка. И да, strbufr использовать не нужно. И ia & boost::serialization::binary_object(a, sizeof(MyClass)); приводит к ошибке компиляции. Решение состоит в том, чтобы использовать make_binary_object вместо binary_object, поскольку он возвращает константный объект, ссылка на который может быть взята и использована классом ускоренной сериализации. - person Jerry; 23.05.2018
comment
@IranjeetSingh Я расширил свой ответ. Вам это нравится? - person JHBonarius; 23.05.2018
comment
Спасибо @JHBonarius. Да, это решение работает по назначению. - person Jerry; 23.05.2018
comment
Привет @JHBonarius. Я пытаюсь сделать шаг вперед в той же программе, указатели, которые я пытался сериализовать и десериализовать, теперь присутствуют в файле std::map<int, MyClass *> MyMap. Опять же, сериализация MyMap в целом работает нормально, но получение этих указателей из пула во время десериализации для меня по-прежнему является проблемой. - person Jerry; 23.05.2018
comment
@IranjeetSingh Я предлагаю вам открыть новый вопрос. Вы можете обратиться к этому вопросу. Но новые вопросы относятся к новой теме. - person JHBonarius; 23.05.2018

Я бы предложил создать обёртку значения или иметь собственный интеллектуальный указатель с пользовательской логикой сериализации.

Способ binary_object будет работать, но только для типов данных POD.

person sehe    schedule 23.05.2018
comment
Мой класс всегда будет содержать только примитивные типы данных. Итак, если метод binary_object будет работать, почему он не компилируется. В коде может быть ошибка. Можете ли вы дать какой-либо совет или предложение? - person Jerry; 23.05.2018
comment
Я согласен. Позже, когда у меня будет время, я вернусь к этому. - person sehe; 23.05.2018
comment
Привет, @sehe, я пытаюсь сделать шаг вперед в той же программе, указатели, которые я пытался сериализовать и десериализовать, теперь присутствуют в std::map‹int, MyClass *› MyMap. Опять же, сериализация MyMap в целом работает нормально, но получение этих указателей из пула во время десериализации для меня по-прежнему является проблемой. - person Jerry; 23.05.2018