Повысить сериализацию: SIGABRT при десериализации boost :: shared_ptr для объекта, содержащего std :: shared_ptr - PullRequest
0 голосов
/ 26 марта 2019

Я пытаюсь выполнить сериализацию и десериализацию boost::shared_ptr для объекта, содержащего std::shared_ptr.

Для этого я использую boost::archive::binary_oarchive и boost::archive::binary_iarchive. Все идет хорошо, но когда экземпляр binary_iarchive выходит из области видимости, я получаю SIGABRT. Вот мой код:

#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/serialization.hpp>

#include <boost/serialization/shared_ptr.hpp>
#include <sstream>

#include <boost/shared_ptr.hpp>

class SomeClass
{
private:
    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int file_version) {
    }
};

class ClassWithStdSharedPointer
{
public:
    std::shared_ptr<SomeClass> ptr_to_someclass;

    friend class boost::serialization::access;
    template<class Archive>
    void serialize(Archive &ar, const unsigned int file_version)
    {
        ar & ptr_to_someclass;
    }
};

int main()
{
    boost::shared_ptr<const ClassWithStdSharedPointer> ptr_to_save;
    ptr_to_save = boost::make_shared<ClassWithStdSharedPointer>();

    std::ostringstream ostream;
    boost::archive::binary_oarchive oa(ostream);
    oa << ptr_to_save;

    std::string serialized_buffer = ostream.str();
    std::istringstream istream(serialized_buffer);

    {
        boost::archive::binary_iarchive ia(istream);

        boost::shared_ptr<ClassWithStdSharedPointer> ptr_to_load;

        ia >> ptr_to_load;
    } 
} // the problem appears when you get to this line

Я использую Boost 1.62, который позволяет сериализовать std::shared_ptr.

После некоторых исследований я выяснил, что SIGABRT происходит, когда вызывается деструктор класса shared_ptr_helper (соответствующий код можно найти в файле serialization/shared_ptr_helper.hpp библиотеки boost). У этого класса есть экземпляр std::map, который используется для хранения десериализованных указателей.

Код сериализации для std::shared_ptr почти такой же, как для boost::shared_ptr (файл serialization/shared_ptr.hpp). На самом деле они оба используют один экземпляр shared_ptr_helper. Следовательно, std::map, описанный выше, содержит оба типа shared_ptr, но он должен содержать только один тип, и это вызывает SIGABRT при вызове деструктора.

Сериализационный код получает помощник по идентификатору, указанному выше в serialization/shared_ptr.hpp. Если мы используем разные идентификаторы для разных типов shared_ptr, проблема исчезнет. Я понимаю, что это делается для обработки ситуаций, когда несколько указателей на один и тот же объект сериализуются, но очень маловероятно, что в этом случае кто-то будет использовать как std::shared_ptr, так и boost::shared_ptr.

Итак, что здесь происходит? Использование обоих типов shared_ptr - это плохая практика, и я должен просто выбрать один из них, или есть ошибка в boost?

1 Ответ

0 голосов
/ 27 марта 2019

Я нашел вопрос , где обсуждается другая проблема с shared_ptr_helper. Похоже, этот класс на самом деле имеет некоторые недостатки дизайна, поэтому в моем случае я должен просто оставить в коде только один тип shared_ptr.

...