Fehler beim Laden von Boost Serialiesierung
-
Hallo zusammen,
ich versuche den folgenden Code zu serialiesieren aber ich bekomme einen Fehler, wenn ich versuche die Sachen zu laden. Ich habe
loadAudi()
hinzugefügt, um nur zu sehen, ob das Laden funktioniert. Ich weiß, dass der pointer im Laden zerstört wird aber darum geht's nicht. Es geht umar& audi
. Das Ergebnis des Codes ist auch unten.Der Code:
#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; }
Und das Ergebnis:
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
Man sieht, dass nach "3" der Fehler kommt. D.h. es gibt ein Problem beim
ar& audi
. Hat jemand eine Idee woran es liegen kann? Danke im Voraus!
-
Du gibst ne Referenz aufn Objekt zurück, das in einem shared_ptr lokal gehalten wird.
Und Zeile 106 sollte so schon mal überhaupt nicht kompilieren, weil die Referenz nicht initialisiert ist. Ist das der echte Quelltext?
-
@DocShoe: Zeile 106 ist keine Referenz, sondern der überladene
&
-Operator für die Serialisierung ('archive').
-
@mika000 sagte in Fehler beim Laden von Boost Serialiesierung:
make_binary_object
Warum nutzt du das? Laut Doku nimmt das Ding einen void* und eine Länge und ist dazu geeignet, Binärdaten zu speichern. Wenn du da die Internals eines Shared Pointers speicherst, erscheint das falsch.
(ich kenne mich mit boost::serialization nicht aus)
-
@Th69 sagte in Fehler beim Laden von Boost Serialiesierung:
@DocShoe: Zeile 106 ist keine Referenz, sondern der überladene
&
-Operator für die Serialisierung ('archive').Autsch, jau.
@mika000
Was passiert denn, wenn du mit demn Debugger im Einzelschritt durch dein Programm läufst? Es scheint ja iwo zwischen 3) und 4) zu scheppern, kannst du mit dem Debugger nicht feststellen, wo genau das passiert?
-
Also:
- Schreib den shared_ptr direkt raus. Einfach
ar & audi;
, nichts mitmake_binary_object
(von dem du auch den Rückgabewert ignorierst) - Lies einfach den shared::ptr<Car> wieder ein.
std::shared_ptr<Car> audi; ar & audi;
. Und dann keine merkwürdigen Dinge bei der Rückgabe aus der load-Funktion tun. Boost::serialization kommt mit Standard-Smartpointern klar.
- Schreib den shared_ptr direkt raus. Einfach
-
Danke euch für die Hilfe. Ich habe das folgende gemacht:
- in
save()
habe ichar& audi
hinzugefügt. - ich habe alles mit
make_binary_object
gelöscht
Der große Fehler war, dass
ar& audi
nicht serialisiert wurde. Also 1 hat alles geändert. Und dann habe ich ich anstattAudi& loadAudi()
einfachAudi loadAudi()
gemacht und der Code hat compiliert/funktioniert.@wob Meintest du in
loadAudi()
für 1&2?
- in