2013-12-15 28 views
5

以下の例では、生のCポインタとそのデータをシリアル化して逆シリアル化しようとしています。それはうまくシリアル化するようだが、私はそれをdeserializeにする方法がわかりません - それは私がそれを逆シリアル化するときにメモリアクセス違反の例外でクラッシュします。それは、それを逆シリアル化する方法を知っていないからだと思いますが、どこでそれを指定しますか?ベクターを用いて生のC配列の逆シリアル化、逆シリアル化

はオプションではありません非常に大規模なプリミティブデータにデシリアライズしながら、それは

#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; 
} 

答えて

8

...あなたはMonkeyはメンバーを初期化しません、手始めに:)

これを台無しので、私は心から、あなたがここにstd::arrayまたはstd::vectorを使用することを推奨します。したがって、ローディングはm.arrのポインタ値に関係なく、load_binaryを実行して終了します。どのようにして、デシリアライゼーションがメモリを割り当てる必要があることを「知っている」と思いますか?

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); 
    } 

を、(初期化と破壊を追加し、そして、おそらく最も重要なのは、コピー・セマンティクスを禁止することによって)さんはMonkeyが少し少なく危険な作りましょう:

struct Monkey 
{ 
    uint32_t num; 
    float* arr; 

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

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

今、あなたはそれを伝える必要があります、あなたはそれが動作を確認できます。

#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, ";")); 
} 

プリント

私はm.numは私がそれをデシリアライズそれまでは知らない任意のarbitary数の可能性があることを考えると、このメモリを割り当てるにはどうすればよい/
0;1;2;3;4;5;6;7;8;9; 

Live on Coliru

+1

私は自分の答えを書くようになりましたが、@すべてのコードとすべての問題を既に入れました。私は要約を追加するだけで、ここにある内容を言い換えるだけです。あなたの本当の問題は、デシリアライズそのものではなく、メモリ管理です。 struct Monkeyが使用するメモリの割り当て、コピー、または割り当て解除の仕方は指定していません。 Seheは、このメモリ管理の問題を解決する2つのきれいな方法を提供しました(ベクトルを使用するか、コピーctor、dtorなどを追加/削除します)。 –

2

痛々しいほど遅い量、m.arrは10個のfloatの配列に、しかしfloat*に初期化されていません。

float*の代わりにMonkey::arrにします。 Boostのシリアライゼーションは、C++標準ライブラリからすべてのコンテナをシリアライズおよびデシリアライズする方法を知っています。

+0

? – KaiserJohaan

+0

私は分かりません。しかし 'float * 'の代わりに' Monkey :: arr'を 'std :: vector 'にすることができます。 Boostのシリアライゼーションは、C++標準ライブラリからすべてのコンテナをシリアライズおよびデシリアライズする方法を知っています。 – Oswald

+0

残念ながらそれはできません。私はコードスニペットの前に書いたように、大量のデータ(3dメッシュとイメージデータがたくさんあります)を扱っています。逆シリアル化するには時間がかかりすぎます。(分!) – KaiserJohaan

関連する問題