提升序列化的输入流错误
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 个问题。
- 您没有通过
ar << audi
调用在 save
方法中序列化 audi
对象。
- 您 return 从
loadAudi
函数引用了 audi
对象。您引用的这个对象在您退出该函数后立即被销毁。
我正在尝试加载序列化内容,但一直无法解决问题。我把它归结为一行特定的代码。我试图尽可能地减少代码,但也展示了一些调试。 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 个问题。
- 您没有通过
ar << audi
调用在save
方法中序列化audi
对象。 - 您 return 从
loadAudi
函数引用了audi
对象。您引用的这个对象在您退出该函数后立即被销毁。