2013-12-15 4 views
5

Ich versuche, rohe C-Zeiger und ihre Daten zu serialisieren und zu deserialisieren, mit dem Beispiel unten. Es scheint serialisieren gut, aber ich bin mir nicht sicher, wie es deserialize - es stürzt nur mit einer Speicherzugriffsverletzung Ausnahme, wenn ich es deserialize. Ich nehme an, es ist, weil es nicht wissen kann, wie man es deserialisiert, aber wo soll ich das spezifizieren?Boost Serialisierung, Deserialisierung von Raw C-Arrays

unter Verwendung eines Vektors ist keine Option, in sehr großen primitiven Datenmengen es quälend langsam ist

#include <stdint.h> 
#include <string> 
#include <iostream> 
#include <fstream> 
#pragma warning (push) 
#pragma warning(disable : 4244) 
#include <boost/serialization/serialization.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/string.hpp> 
#include <boost/serialization/array.hpp> 
#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 
#pragma warning (pop) 

struct Monkey 
{ 
    uint32_t num; 
    float* arr; 

}; 


namespace boost 
{ 
    namespace serialization 
    { 
     template<class Archive> 
     void serialize(Archive & ar, Monkey& m, const unsigned int version) 
     { 
      ar & m.num; 
      ar & make_array<float>(m.arr, m.num); 
     } 
    } 
} 


int _tmain(int argc, _TCHAR* argv[]) 
{ 
    const char* name = "monkey.txt"; 

    { 
     Monkey m; 
     m.num = 10; 
     m.arr = new float[m.num]; 
     for (uint32_t index = 0; index < m.num; index++) 
      m.arr[index] = (float)index; 

     std::ofstream outStream(name, std::ios::out | std::ios::binary | std::ios::trunc); 
     boost::archive::binary_oarchive oar(outStream); 
     oar << (m); 
    } 

    Monkey m; 
    std::ifstream inStream(name, std::ios::in | std::ios::binary);  
    boost::archive::binary_iarchive iar(inStream); 
    iar >> (m); 

    return 0; 
} 

Antwort

8

empfehle ich Ihnen herzlich verwenden std::array oder std::vector hier, weil ... Sie dies :) verkorkste

Für den Anfang hat Monkey nicht seine Mitglieder initialisieren. Also, Laden endet mit einer load_binary zu was auch immer Zeiger-Wert m.arr passiert ist. Wie würden Sie erwarten, dass die Deserialisierung "weiß", dass Sie Speicher dafür reservieren müssen? Sie müssen sagen, es:

template<class Archive> 
    void serialize(Archive & ar, Monkey& m, const unsigned int version) 
    { 
     ar & m.num; 
     if (Archive::is_loading::value) 
     { 
      assert(m.arr == nullptr); 
      m.arr = new float[m.num]; 
     } 
     ar & make_array<float>(m.arr, m.num); 
    } 

Jetzt wollen wir Monkey etwas weniger unsicher machen (durch Initialisierung und Zerstörung hinzugefügt, und, vielleicht am wichtigsten ist, zu kopieren Semantik Verbot):

struct Monkey 
{ 
    uint32_t num; 
    float* arr; 

    Monkey() : num(0u), arr(nullptr) {} 

    Monkey(Monkey const&) = delete; 
    Monkey& operator=(Monkey const&) = delete; 
    ~Monkey() { delete[] arr; } 
}; 

Jetzt , können Sie es arbeiten sehen:

#include <iostream> 
#include <fstream> 
#pragma warning(disable: 4244) 
#include <boost/serialization/serialization.hpp> 
#include <boost/archive/binary_oarchive.hpp> 
#include <boost/archive/binary_iarchive.hpp> 

struct Monkey 
{ 
    uint32_t num; 
    float* arr; 

    Monkey() : num(0u), arr(nullptr) {} 

    Monkey(Monkey const&) = delete; 
    Monkey& operator=(Monkey const&) = delete; 
    ~Monkey() { delete[] arr; } 
}; 

namespace boost 
{ 
    namespace serialization 
    { 
     template<class Archive> 
     void serialize(Archive & ar, Monkey& m, const unsigned int version) 
     { 
      ar & m.num; 
      if (Archive::is_loading::value) 
      { 
       assert(m.arr == nullptr); 
       m.arr = new float[m.num]; 
      } 
      ar & make_array<float>(m.arr, m.num); 
     } 
    } 
} 

int main(int argc, char* argv[]) 
{ 
    const char* name = "monkey.txt"; 
    { 
     Monkey m; 
     m.num = 10; 
     m.arr = new float[m.num]; 
     for (uint32_t index = 0; index < m.num; index++) 
      m.arr[index] = (float)index; 

     std::ofstream outStream(name, std::ios::out | std::ios::binary | std::ios::trunc); 
     boost::archive::binary_oarchive oar(outStream); 
     oar << (m); 
    } 

    Monkey m; 
    std::ifstream inStream(name, std::ios::in | std::ios::binary); 
    boost::archive::binary_iarchive iar(inStream); 
    iar >> (m); 

    std::copy(m.arr, m.arr + m.num, std::ostream_iterator<float>(std::cout, ";")); 
} 

Drucke

0;1;2;3;4;5;6;7;8;9; 

Live on Coliru

+1

Ich fing an, meine eigene Antwort zu schreiben, aber @sehe legte den gesamten Code und alle Probleme bereits.Ich kann nur meine Zusammenfassung hinzufügen, nur umformulieren, was hier drin ist: Ihr wirkliches Problem ist nicht die Deserialisierung an sich, sondern die Speicherverwaltung. Sie haben nicht angegeben, wie der struct Monkey den von ihm verwendeten Speicher zuweist, kopiert oder freigibt. Sehe gab zwei saubere Möglichkeiten, um dieses Speicherverwaltungsproblem zu lösen (entweder verwende Vektor oder addiere/lösche Kopie ctor, dtor, etc.). –

2

Während Deserialisieren wird m.arr nicht auf ein Array von 10 Schwimmern initialisiert, sondern auf eine float*.

Machen Sie Monkey::arr eine std::vector<float> statt einer float*. Boost-Serialisierung weiß, wie alle Container aus der C++ - Standardbibliothek serialisiert und deserialisiert werden.

+0

Wie/wo kann ich diesen Speicher reservieren, da m.num jede willkürliche Zahl sein könnte, dass ich weiß nicht, bis ich es deserialisieren? – KaiserJohaan

+0

Ich weiß es nicht. Sie könnten aber 'Monkey :: arr' anstelle von' float * '' 'std :: vector ' machen. Boost-Serialisierung weiß, wie alle Container aus der C++ - Standardbibliothek serialisiert und deserialisiert werden. – Oswald

+0

Das kann ich leider nicht machen; Wie ich vor dem Code-Snippet geschrieben habe, habe ich es mit großen Datenmengen zu tun (viele 3D-Meshes und Bilddaten) und es ist zu langsam, um es zu deserialisieren (Minuten!) – KaiserJohaan