Boost Serialization Segfault

依然范特西╮ 提交于 2019-12-02 08:39:40

问题


I am trying to serialize a class member. The following snippet of code will show the relevant class definitions and the non-intrusive serialization code I have included. I am getting a segfault during my saveHashTable() method which tries to serialize the class member shash_table_. Here is a self-contained trimmed version of the code:

#include <map>
#include <string>
#include <vector>
#include <set>
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/vector.hpp>
#include <boost/serialization/set.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/map.hpp>
#include <boost/serialization/list.hpp>

using namespace std;

struct ORROctree
    {
      public:
        struct Node
        {
          public:
            struct Data
            {               
              public:
                float n_[3], p_[3];
                int id_x_, id_y_, id_z_, lin_id_, num_points_;
                std::set<Node*> neighbors_;
                void *user_data_;
            };

          public: 
            Node::Data *data_;
            float center_[3], bounds_[6], radius_;
            Node *parent_, *children_;
        };        
      protected:
        float voxel_size_, bounds_[6];
        int tree_levels_;
        Node* root_;
        std::vector<Node*> full_leaves_;                  
    };

struct ModelLibrary
{  

    template <typename T, typename REAL = float>    
    struct NDIMVoxelStructure 
    {
        T *voxels_;        
        std::vector<int> total_num_of_voxels_i_;
        std::vector<int> num_of_voxels_;
        long total_num_of_voxels_;
        std::vector<REAL> bounds_;
        std::vector<REAL> spacing_; 
        std::vector<REAL> min_center_;
};


    typedef std::pair<const ORROctree::Node::Data*, const ORROctree::Node::Data*>  Dipole;
    struct Base {
         Dipole seg1;
         Dipole seg2;
    };
    typedef std::list<Base> bases_list;
    typedef std::map <string, bases_list> SerializeHashTableCell;
    // MEMBER TO BE SERIALIZED
    typedef NDIMVoxelStructure<SerializeHashTableCell> SerializeHashTable;

  public:
    SerializeHashTable shash_table_;

  public:
    bool saveHashTable();

    bool loadHashTable();
};



// SERIALIZATION METHODS FOR THE TYPES USED TO FORM THE SERIALIZEHASHTABLE


namespace boost {
namespace serialization {

template<class Archive>
inline void serialize(Archive & ar, ModelLibrary::SerializeHashTable & h, const unsigned int version)
{
  ar & h.total_num_of_voxels_;
  ar & boost::serialization::make_array(h.voxels_, h.total_num_of_voxels_);
  ar & h.num_of_voxels_;
  ar & h.total_num_of_voxels_i_;
  ar & h.bounds_;
  ar & h.spacing_;
  ar & h.min_center_;
}


template<class Archive>
inline void serialize(Archive & ar, ModelLibrary::Base & b, const unsigned int version)
{
  ar & b.seg1;
  ar & b.seg2;
}


template<class Archive>
inline void serialize(Archive & ar, ORROctree::Node n, const unsigned int version)
{
  ar & n.data_;
  ar & n.center_;
  ar & n.bounds_;
  ar & n.radius_;
  ar & n.parent_;
  ar & n.children_;
}

template<class Archive>
inline void serialize(Archive & ar, ORROctree::Node::Data d, const unsigned int version)
{
  ar & d.id_x_;
  ar & d.id_y_;
  ar & d.id_z_;
  ar & d.neighbors_;
  ar & d.lin_id_;
  ar & d.num_points_;
  ar & d.p_;
}
}
}

bool ModelLibrary::saveHashTable ()
{
    std::ofstream ofs("test.txt");
    boost::archive::text_oarchive oa(ofs);
    oa << shash_table_;
    return true;
}


bool
ModelLibrary::loadHashTable ()
{
    std::ifstream ifs("test.txt");
    boost::archive::text_iarchive ia(ifs);
    ia >> shash_table_;
    return true;
}


int main() 
{
    ModelLibrary m;
    m.saveHashTable();
}

回答1:


You just need to initialize the data in your data structures. All primitive types that haven't been explicitely initialized will have indeterminate ("random") values. This includes the pointers, which means you're invoking Undefined Behaviour by dereferencing pointers to random memory locations.

Here's an update with the simplest initialization that could possibly work, and it runs clean under Valgrind. That's a good tool. Use it!

Also, crank up the compiler messages (-Wall -Wextra -pedantic at a minimum for gcc/clang).

Added in various places:

Data() : id_x_(0), id_y_(0), id_z_(0), lin_id_(0), num_points_(0), user_data_(0)
{
    std::fill(n_, n_+3, 0);
    std::fill(p_, p_+3, 0);
}
Node() : data_(0), radius_(0), parent_(0), children_(0) 
{
    std::fill(center_, center_+3, 0);
    std::fill(bounds_, bounds_+6, 0);
}
ORROctree() : voxel_size_(0), tree_levels_(0), root_(0)
{
    std::fill(bounds_, bounds_+6, 0);
}
NDIMVoxelStructure() : voxels_(0), total_num_of_voxels_(0) 
{ }
Base() : seg1(0, 0), seg2(0, 0) 
{ }

See it Live On Coliru

Update From the comment: the following lines were clearly in error:

inline void serialize(Archive & ar, ORROctree::Node n, const unsigned int version)
inline void serialize(Archive & ar, ORROctree::Node::Data d, const unsigned int version)

And should have read

inline void serialize(Archive & ar, ORROctree::Node& n, const unsigned int version)
inline void serialize(Archive & ar, ORROctree::Node::Data& d, const unsigned int version)


来源:https://stackoverflow.com/questions/23175180/boost-serialization-segfault

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!