提升序列化的输入流错误

Input stream error with boost serialization

我正在尝试加载序列化内容,但一直无法解决问题。我把它归结为一行特定的代码。我试图尽可能地减少代码,但也展示了一些调试。 class loadAudi 只是为了说明错误的来源,并且仅用于帮助调试问题的目的。 loadAudi 中的 ar& audi 行是导致错误的原因。在“真实”代码中, boost::archive::binary_iarchive ar(in_f); 之后的 ar& audi 是导致问题的原因。这是代码(完整的输出在底部):

#include <armadillo>

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/serialization/assume_abstract.hpp>
#include <boost/serialization/serialization.hpp>
#include <boost/serialization/split_member.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/unique_ptr.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/void_cast_fwd.hpp>
#include <boost/serialization/binary_object.hpp>

#include <iostream>
#include <fstream>
#include <memory>
#include <sstream>
#include <vector>

class Engine
{
public:
    Engine () {}
    Engine (const int cyl) : _cyl ( cyl ) {}
    int getCyl () const { return _cyl; }

private:
    int _cyl;

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

class Car {
public:
    virtual char const* type() const = 0;
    virtual void printMember () const = 0;
    virtual void save (const std::string file) const { std::cout << "file" << std::endl; };

    virtual ~Car() = default;

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

class Audi : public Car, public std::enable_shared_from_this<Car> {
public:

Audi() {};
Audi(const std::string owner, const int hp,const unsigned int cyl)
    : _owner ( owner ),
    _hp    ( hp ),
    _eng          ( std::make_shared<Engine>(cyl) )
{ }

char const* type() const override { return "Audi"; }

void printMember () const override
{
    std::cout
    << this->type() << ":\n"
    << "owner: " << _owner
    << " hp: " << _hp
    << " engine: " << _eng->getCyl()
    << std::endl;
}
void save (const std::string file) const {
    std::ofstream of(file, std::ofstream::binary);
    std::stringstream strs;
    boost::archive::binary_oarchive ar(of);
    std::shared_ptr<const Car> audi = shared_from_this();
    boost::serialization::make_binary_object(&audi, sizeof(audi));
}

private:
std::string  _owner;
int          _hp;
std::shared_ptr<Engine> _eng;

friend class boost::serialization::access;
template <class Archive>
void serialize(Archive& ar, const unsigned int version) {
    ar & boost::serialization::base_object<Car>(*this);
    ar & _owner;
    ar & _hp;
    ar & _eng;
}
};

Audi& loadAudi (const std::string file_name) {
std::cout << "Loading " << file_name << std::endl;
std::ifstream in_f(file_name, std::ifstream::binary);

std::cout << "1" << std::endl;
std::shared_ptr<Car> audi; //= std::make_unique<Audi>();

std::cout << "2" << std::endl;
boost::archive::binary_iarchive ar(in_f);

std::cout << "3" << std::endl;
ar& audi;

std::cout << "4" << std::endl;
return dynamic_cast<Audi &>(*audi);
};

BOOST_CLASS_EXPORT(Audi);
BOOST_CLASS_EXPORT(Engine);
BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car); //Tell Boost that Car is abstract

int main() {
std::string save_file = "test.dat";
std::ofstream of(save_file, std::ofstream::binary);
std::ifstream in_f(save_file, std::ifstream::binary);
{
    std::shared_ptr<Car> audi = std::make_shared<Audi>("Wilma", 3, 16);
    audi->printMember();

    std::stringstream strs;
    boost::archive::binary_oarchive ar(of);
    ar& audi;

    // audi_save_dir = strs.str();
    std::cout << "Count of audi:" << audi.use_count() << std::endl;

    ar << boost::serialization::make_binary_object(&audi, sizeof(audi));
}


{
    std::shared_ptr<Car> audi; //= std::make_unique<Audi>();
    std::cout << "Deserialize: Count of audi:" << audi.use_count() << std::endl;

    //std::stringstream strs(f);
    boost::archive::binary_iarchive ar(in_f);
    ar& audi;
    Audi& d = dynamic_cast<Audi &>(*audi);

    std::cout << "Deserialize: Count of audi:" << audi.use_count() << std::endl;
    std::cout << "Print Audi:" << std::endl;
    d.printMember();
}


std::shared_ptr<Car> audi = std::make_shared<Audi>("Daniel", 200, 8);
audi->printMember();

std::string test_dat = "my-new-audi.dat";
audi->save(test_dat);
Audi& d =  loadAudi(test_dat);
d.printMember();

return 0;
}

输出:

Audi:
owner: Wilma hp: 3 engine: 16
Count of audi:1
Deserialize: Count of audi:0
Deserialize: Count of audi:2
Print Audi:
Audi:
owner: Wilma hp: 3 engine: 16
Audi:
owner: Daniel hp: 200 engine: 8
Loading my-new-audi.dat
1
2
3
terminate called after throwing an instance of 'boost::archive::archive_exception'
what():  input stream error
[2]    29888 abort      ./a.out

如有任何帮助,我将不胜感激!

这里有 2 个问题。

  1. 您没有通过 ar << audi 调用在 save 方法中序列化 audi 对象。
  2. 您 return 从 loadAudi 函数引用了 audi 对象。您引用的这个对象在您退出该函数后立即被销毁。