Boost Serialisation Problem



  • Hi!

    ich hab ein problem mit der Boost Serialisation.
    Immer wenn die Anzahl an Unterklassen zu groß wird kann ich die Files nicht mehr Laden. Das es an der Größe liegt bezweifel ich, aber der fehler ist jedenfalls so reproduzierbar...

    Das Programm:

    _IndexCluster z(0, 1, 2);
    
    	for(int i = 0; i < 10; i++) {
    		_IndexCluster a(i, i*1000, i*1000);
    		for(int j = 0; j < 100; j++) { //Wähle ich hier z.B: j < 10 funktioniert es... kein crash...
    			_IndexCluster b(j*i, j*i*10, j*i*100);
    			a.insert(b);
    		}
    		z.insert(a);
    	}
    
    	ofstream treeout("bla.Arv");
    	{
    		boost::archive::binary_oarchive oa(treeout);
    		oa << z;
    	}
    
    	_IndexCluster n;
        {
            std::ifstream treein("bla.Arv");
    		boost::archive::binary_iarchive ia(treein);
            ia >> n;	// crash!
        }
    

    Die Klasse:

    class _IndexCluster {
    	public:
    		 _IndexCluster();
    		 _IndexCluster(_u32 key, _u32 byteOffset);
    		 _IndexCluster(_u32 key, _u32 byteOffset, _u32 size);
    		~_IndexCluster();
    
    		void					insert			(_IndexCluster obj);
    
    	private:
    		friend class boost::serialization::access;
    		template<class Archive>
    		void	serialize(Archive& ar, _u16 version) {
    			ar & m_Key;
    			ar & m_byteOffset;
    			ar & m_Size;
    			ar & m_subCluster;
    		}
    
    		_u32					m_Key;
    		_u32					m_byteOffset;
    		_u32					m_Size;
    		vector<_IndexCluster>	m_subCluster;
    };
    


    1. Du solltest keine reservierten Bezeichner verwenden.
    2. std::vector mit nem incomplete type? Ich denke nicht dass das geht.
    3. Guck mal wo es crasht, und wieso. Mit nem Debugger geht das sehr leicht. Rumraten ist relativ unspannend.


  • hustbaer schrieb:

    1. Guck mal wo es crasht, und wieso. Mit nem Debugger geht das sehr leicht. Rumraten ist relativ unspannend.

    Die exakte stelle ist im code angegeben. In den Boost funrktionen rumdebuggen macht keinen spaß, das ist zu komplex.

    Was meinst du mit reservierten Bezeichner?
    Das problem liegt sicher in der Speicherverwaltung. Irgendwas rechnet nicht damit das so viel Speicher gebraucht wird und schreibt in Bereiche die nicht zulässig sind -> exception.

    Aber wie sorge ich dafür das entweder boost schnallt das es mehr platz braucht, oder wie weise ich meiner Zielklasse wo reingeschrieben wird mehr speicher zu?

    edit: Das hier ist die Fehlermeldung die kommt.

    Unhandled exception at at 0x758EC41F in StreamParsing.exe: Microsoft C++ exception: boost::archive::archive_exception at memory location 0x003C61EC.
    

    gruß,
    Chris



  • cl90 schrieb:

    Was meinst du mit reservierten Bezeichner?

    Unterstrich am Anfang gefolgt von GROSSBUCHSTABEN.

    Es fehlt ein kompilierbares Beispiel. Das musst Du noch liefern.

    Beachte dabei auch hustbaers Hinweis auf incomplete types .
    Nicht jeder Compiler schluckt es, wenn Du solche in stl Container steckst. (Es ist sogar explizit nicht erlaubt!)

    #include <vector>
    
    struct gadget{
      std::vector<gadget> v; // gadget ist hier nur deklariert (aka incomplete)
    };
    

    Ergibt:

    Furble Wurble@sinsemilla /tmp $ g++ -c -std=c++11 -Wall -pedantic -g -D_GLIBCXX_CONCEPT_CHECKS -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC bla.cc -o bla.o
    In file included from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/concept_check.h:55:0,
                     from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/move.h:34,
                     from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/stl_pair.h:61,
                     from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/stl_algobase.h:65,
                     from /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/vector:61,
                     from bla.cc:1:
    /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/boost_concept_check.h: In instantiation of ‘struct __gnu_cxx::_SGIAssignableConcept<gadget>’:
    /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/stl_vector.h:212:1:   required from ‘class std::__cxx1998::vector<gadget, std::allocator<gadget> >’
    /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/debug/vector:45:11:   required from ‘class std::__debug::vector<gadget>’
    bla.cc:4:23:   required from here
    /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/include/g++-v4/bits/boost_concept_check.h:214:9: error: ‘__gnu_cxx::_SGIAssignableConcept<_Tp>::__a’ has incomplete type
    bla.cc:3:8: error: forward declaration of ‘struct gadget’
    [...]
    

    Beachte Z.12.

    Du kannst z.B. auf boost::container::vector ausweichen. Damit gibt es bei mir z.B. keine Probleme. (Etwas nach Lust und Laune umbenamst und umgestellt):

    #include <iostream>
    #include <fstream>
    
    #include <boost/container/vector.hpp>
    #include <boost/archive/binary_oarchive.hpp>
    #include <boost/archive/binary_iarchive.hpp>
    
    class indexcluster : private boost::container::vector<indexcluster> {
      using impl = boost::container::vector<indexcluster>;
    public:
      indexcluster(uint32_t key=0u, uint32_t byteOffset=0u, uint32_t size=0u)
        : m_Key{key}, m_byteOffset{byteOffset}, m_Size{size}
      {
      }
      using impl::push_back;
    private:
      friend class boost::serialization::access;
      template<class Archive>
      void    serialize(Archive& ar, const unsigned int version) {
        ar & boost::serialization::base_object<impl>(*this);
        ar & m_Key;
        ar & m_byteOffset;
        ar & m_Size;
      }
    
      uint32_t                    m_Key;
      uint32_t                    m_byteOffset;
      uint32_t                    m_Size;
    };
    
    template<class Archive>
    void serialize(Archive & ar, boost::container::vector<indexcluster>& v, const unsigned int version)
    {
      for(auto& a : v)
        ar & a;
    }
    
    int main(){
      indexcluster z(0, 1, 2);
    
      for(int i = 0; i < 10; i++) {
        indexcluster a(i, i*1000, i*1000);
        for(int j = 0; j < 100; j++) { //Wähle ich hier z.B: j < 10 funktioniert es... kein crash...
          indexcluster b(j*i, j*i*10, j*i*100);
          a.push_back(b);
        }
        z.push_back(a);
      }
    
      std::ofstream treeout("bla.Arv");
      {
        boost::archive::binary_oarchive oa(treeout);
        oa << z;
      }
    
      indexcluster n;
      {
        std::ifstream treein("bla.Arv");
        boost::archive::binary_iarchive ia(treein);
        ia >> n;    // crash!
      }
    }
    


  • cl90 schrieb:

    hustbaer schrieb:

    1. Guck mal wo es crasht, und wieso. Mit nem Debugger geht das sehr leicht. Rumraten ist relativ unspannend.

    Die exakte stelle ist im code angegeben. In den Boost funrktionen rumdebuggen macht keinen spaß, das ist zu komplex.

    Debuggen macht meistens kaum Spaß, weil es eben Fehlersuche ist.

    cl90 schrieb:

    Was meinst du mit reservierten Bezeichner?

    Bezeichner, die mit einem oder zwei Unterstrichen anfangen sind für den Compilerhersteller reserviert. D.h. der könnte standardkonform ein Makro haben welches _IndexCluster heisst und bei Benutzung die Festplatte formatiert.

    cl90 schrieb:

    Das problem liegt sicher in der Speicherverwaltung. Irgendwas rechnet nicht damit das so viel Speicher gebraucht wird und schreibt in Bereiche die nicht zulässig sind -> exception.

    Das Problem liegt "sicher" irgendwo?!
    Und sowenig Speicher wie du da bräuchtest, da lacht ein heutiger Computer aus Langeweile drüber (~1000000 Elemente.....)



  • Hallo Leute,

    Danke für die vielen Tipps, letztendlich lag es daran das ich die fstreams nicht mit ios::binary geöffnet habe. Ich werde vlt tozdem den Boost vector einmal austesten und sehen ob der vieleicht weniger Overhead in den Fieles erzeugt.

    Ich weiß das mit den reservierten Bezeichnern gefällt mir auch nicht, aber es ist hier in der Programmiergruppe so im StyleGuide verankert.

    Gruß,
    Chris


Log in to reply