2017-03-03 52 views
1

我有一个类gamma,如下所示。shared_ptr的介绍导致反序列化时出现分段错误(使用boost :: serialization)

当make_nvp函数尝试反序列化现有的xml文件时,加载函数会引发段错误。该错误是当我使用std::shared_ptr<std::tuple<double,double,double>> val;

相反,如果VAL只是std::tuple<double,double,double> val;

然后一切似乎很好地工作(当然,我改变了getter和setter函数相应)。

现在我回顾了一堆关于stackoverflow的问题,我用google搜索了一下boost文档中的例子,我弄不明白为什么load函数会导致程序以分段错误终止。

注:互联网(以及计算器一些老问题)上的一些旧文章似乎在暗示用在那个时间点与升压序列化到不行那的std :: shared_ptr的。我不认为2017年会出现这种情况。不管怎样,只是可以肯定的是,我尝试用boost :: shared_ptr替换std :: shared_ptr,并且分段错误仍然存​​在。

我不明白为什么会出现错误?

gamma.h

#pragma once 
#include <map> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/nvp.hpp> 
#include <boost/serialization/map.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/utility.hpp> 
#include <boost/serialization/shared_ptr.hpp> 

#include <tuple> 

namespace boost 
{ 
    namespace serialization 
    { 
     template<typename Archive> 
     void serialize(Archive & ar, std::tuple<double, double, double> & t, 
        const unsigned int version) 
     { 
      ar & boost::serialization::make_nvp("t0",std::get<0>(t)); 
      ar & boost::serialization::make_nvp("t1",std::get<1>(t)); 
      ar & boost::serialization::make_nvp("t2",std::get<2>(t)); 
     } 

    } 
} 

class Gamma 
{ 
public: 
    static void save(std::ostream& os); 
    static void load(std::istream& is); 

    std::shared_ptr<std::tuple<double, double, double>> getterX() const; 
    void setterX(const std::tuple<double, double, double> &val); 

private: 

    std::shared_ptr<std::tuple<double,double,double>> val; 

    friend class boost::serialization::access; 
    template<typename Archive> 
    void serialize(Archive& arc, const unsigned int version) 
    { 
      arc & boost::serialization::make_nvp("val", val); 
    } 
}; 

和gamma.cpp

#include "gamma.h" 
#include <boost/archive/xml_iarchive.hpp> 
#include <boost/archive/xml_oarchive.hpp> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/nvp.hpp> 
#include <boost/serialization/utility.hpp> 

Gamma &Gamma::instance() 
{ 
    static Gamma obj; 
    return obj; 
} 

std::shared_ptr<std::tuple<double, double, double>> Gamma::getterX() const 
{ 
    return val; 
} 

void Gamma::setterX(const std::tuple<double, double,double> &v) 
{ 
    if (nullptr == val) { 
     m_touchDownCalibration = std::make_shared<std::tuple<double, double,double>>(); 
    } 
    *val = v; 
} 

const char* TAG = "tag"; 

void Gamma::save(std::ostream& os) 
{ 
    boost::archive::xml_oarchive arc(os); 
    arc & boost::serialization::make_nvp(TAG,instance()); 
} 

void Gamma::load(std::istream& is) 
{ 
    boost::archive::xml_iarchive arc(is); 
    arc & boost::serialization::make_nvp(TAG,instance()); 
} 
+0

你的代码不完整,不能按原样编译。 – overseas

+0

是的。我只添加了导致问题的类。这是一个更大的项目的一部分,我通过一系列其他课程,从主要开始,到达这个班级。让我再看看,如果我可以用干净的方式在这里添加这些类。 –

+0

@overseas,在最后两个函数load()和save()的类名中也有一个小错误。我现在纠正了。 用户sehe添加了一个main()来调用这个类,看起来他在那里没有分段错误。嗯,好奇!可能seg故障是由其他原因引起的。将在几个小时内检查。 –

回答

1

这是一个神秘的我是什么一个shared_ptr实际上可以添加到一个元组里面......一个单身。但不管怎么说,我做你的代码独立的,它的工作原理:

Live On Coliru

我希望你能找出哪一部分,您做了不同的/错误:

#include <map> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/nvp.hpp> 
#include <boost/serialization/map.hpp> 
#include <boost/serialization/vector.hpp> 
#include <boost/serialization/utility.hpp> 
#include <boost/serialization/shared_ptr.hpp> 

#include <tuple> 

namespace boost { namespace serialization { 
    template<typename Archive> 
    void serialize(Archive & ar, std::tuple<double, double, double> & t, unsigned) { 
     ar & boost::serialization::make_nvp("t0", std::get<0>(t)); 
     ar & boost::serialization::make_nvp("t1", std::get<1>(t)); 
     ar & boost::serialization::make_nvp("t2", std::get<2>(t)); 
    } 
} } 

class CalibrationDataObject 
{ 
public: 
    static CalibrationDataObject &instance(); 
    static void save(std::ostream& os); 
    static void load(std::istream& is); 

    std::shared_ptr<std::tuple<double, double, double>> getterX() const; 
    void setterX(const std::tuple<double, double, double> &val); 

private: 
    std::shared_ptr<std::tuple<double,double,double>> val; 

    friend class boost::serialization::access; 
    template<typename Archive> 
    void serialize(Archive& arc, unsigned) 
    { 
      arc & boost::serialization::make_nvp("val", val); 
    } 
}; 

//#include "CalibrationDataObject.h" 
#include <boost/archive/xml_iarchive.hpp> 
#include <boost/archive/xml_oarchive.hpp> 
#include <boost/serialization/access.hpp> 
#include <boost/serialization/nvp.hpp> 
#include <boost/serialization/utility.hpp> 

CalibrationDataObject &CalibrationDataObject::instance() { static CalibrationDataObject obj; return obj; } 

std::shared_ptr<std::tuple<double, double, double>> CalibrationDataObject::getterX() const { 
    return val; 
} 

void CalibrationDataObject::setterX(const std::tuple<double, double,double> &v) 
{ 
    if (val) 
     *val = v; 
    else 
     val = std::make_shared<std::tuple<double, double,double>>(v); 
} 

const char* TAG = "tag"; 

void CalibrationDataObject::save(std::ostream& os) 
{ 
    boost::archive::xml_oarchive arc(os); 
    arc & boost::serialization::make_nvp(TAG,instance()); 
} 

void CalibrationDataObject::load(std::istream& is) 
{ 
    boost::archive::xml_iarchive arc(is); 
    arc & boost::serialization::make_nvp(TAG,instance()); 
} 

#include <fstream> 

int main() { 
    { 
     std::ofstream ofs("test.data"); 
     CalibrationDataObject::save(ofs); 
    } 
    { 
     std::ifstream ifs("test.data"); 
     CalibrationDataObject::load(ifs); 
    } 
} 

打印以下数据:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> 
<!DOCTYPE boost_serialization> 
<boost_serialization signature="serialization::archive" version="14"> 
<tag class_id="0" tracking_level="0" version="0"> 
    <val class_id="1" tracking_level="0" version="1"> 
     <px class_id="-1"></px> 
    </val> 
</tag> 
</boost_serialization> 
+0

嗨。感谢您忽略我忘记将最后两个函数的类(load()和save())从CalibrationDataObject重命名为Gamma的复制/粘贴/编辑错误。:D 给我几个小时,然后我再次回过头来。 是的。你是对的。添加一个shared_ptr似乎在这里什么都没有实现(并且原始代码也没有在这个位置使用shared_ptr),但随后有人(不是我)编辑它(出于某种原因?!?),并且在测试后,我注意到它似乎打破负载功能,这让我好奇。 谢谢你的时间。 –

+0

嗯,我也没有看到任何错误。 :/ 好的。这本身很有帮助。我接受了你的答案。 –

+1

@JoeyMallone也许你正在加载一个与旧版本保存的存档。布局将不兼容(如果要加载旧版本,您必须执行[Class Versioning](http://www.boost.org/doc/libs/1_63_0/libs/serialization/doc/tutorial.html#versioning))档案格式) – sehe

相关问题