问题
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