Boost 序列化段错误
Posted
技术标签:
【中文标题】Boost 序列化段错误【英文标题】:Boost Serialization Segfault 【发布时间】:2014-04-19 20:32:32 【问题描述】:我正在尝试序列化一个班级成员。下面的 sn-p 代码将显示相关的类定义和我包含的非侵入式序列化代码。我在尝试序列化类成员 shash_table_ 的 saveHashTable() 方法期间遇到段错误。这是代码的独立修剪版本:
#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】:您只需要初始化数据结构中的数据。所有未显式初始化的原始类型都将具有 indeterminate(“随机”)值。这包括指针,这意味着您通过取消引用指向随机内存位置的指针来调用 Undefined Behaviour。
这里有一个更新,可能是最简单的初始化,它在 Valgrind 下运行干净。这是一个很好的工具。使用它!
另外,增加编译器消息(gcc/clang 至少为-Wall -Wextra -pedantic
)。
在各个地方添加:
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)
看Live On Coliru
更新来自评论:以下几行显然是错误的:
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)
应该读过
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)
【讨论】:
这个解决方案效果很好,但我遇到了一个不同的问题,我的真实代码有类而不是结构,但具有相同的层次结构和数据成员。出于某种原因,从以 Octree::Node 作为模板参数的序列化函数调用 Octree::Node 的 dtor,并导致语句 delete[] children_(dtor 的一部分)上的段错误。我不确定这是否可以在不查看代码的情况下帮助我,但我不明白为什么 serliazer 会调用 Octree::Node 的 dtor。段错误的堆栈跟踪也显示 600 多个调用 当我使用 valgrind 运行它时,它不会崩溃,但会显示按大小为 8 的无效读取问题,详情请点击此处:docs.google.com/document/d/… 任何见解将不胜感激。已经为此苦苦挣扎了好几个小时。 我什么都说不出来,因为您没有显示任何相关代码(在您提供的代码中,没有一个析构函数,也没有删除)。无论如何,ORROctree::Node::~Node
显然是被调用的,因为您在 serialize
函数中按值传递它,这显然是一个错误(除此之外,检查所有类型的三规则会非常好;再次,您没有显示所有代码,所以我无法帮助您)。我已经用丢失的两个 &
s 修复了代码:Coliru
切线,如果您能提出后续问题新问题,我将不胜感激。以上是关于Boost 序列化段错误的主要内容,如果未能解决你的问题,请参考以下文章
使用 boost::serialization 保存数据时出现 Seg 错误