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 um ar& 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:

    1. Schreib den shared_ptr direkt raus. Einfach ar & audi;, nichts mit make_binary_object (von dem du auch den Rückgabewert ignorierst)
    2. 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.


  • Danke euch für die Hilfe. Ich habe das folgende gemacht:

    1. in save() habe ich ar& audi hinzugefügt.
    2. 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 anstatt Audi& loadAudi() einfach Audi loadAudi() gemacht und der Code hat compiliert/funktioniert.

    @wob Meintest du in loadAudi() für 1&2?


Log in to reply