C++ Boost序列化调用错误的序列化方法

C++ Boost序列化调用错误的序列化方法,c++,boost-serialization,C++,Boost Serialization,我使用了宏对BOOST\u CLASS\u EXPORT\u键(T)作为头文件和BOOST\u CLASS\u EXPORT\u实现(T)作为实现文件,以便序列化从基类指针派生的类 (**注意:我已将宏放入所有需要序列化的头文件和实现文件中,包括基类) 然而,当序列化到特定的类时,我遇到了一个奇怪的问题。我遇到的问题是,当保存时序列化是正确的,但当加载时序列化是错误的,它将调用不同的类序列化方法 更新:仅供参考,在从不同类调用错误的序列化方法后,引发未注册类的异常。代码只在binary\u ar

我使用了
BOOST\u CLASS\u EXPORT\u键(T)
作为文件和
BOOST\u CLASS\u EXPORT\u实现(T)
作为实现文件,以便序列化从类指针派生的

(**注意:我已将宏放入所有需要序列化的头文件和实现文件中,包括基类)

然而,当序列化到特定的类时,我遇到了一个奇怪的问题。我遇到的问题是,当
保存
时序列化是正确的,但当
加载
时序列化是错误的,它将调用不同的类序列化方法

更新:仅供参考,在从不同类调用错误的序列化方法后,引发未注册类的异常。代码只在
binary\u archive
中有问题,并且在
text\u archive
中工作正常,这让我感到困惑,因为我认为如果
text\u archive
序列化正常,那么
binary\u archive
应该没有问题。或者我遗漏了一些需要注意的非常显著的差异

部分代码片段如下所示:

仅供参考,尝试反序列化
子模型层
时会出现此问题<代码>子模型层
也继承节点

template<typename Archive>
void ModelLayer::serialize(Archive & ar, const unsigned int version)
{
    // invoke serialization of the base class 
    ar & boost::serialization::base_object<Node>(*this);
    //this will actually call the 
    //ModelLayerData<_MODEL_LAYER_VERSION_ONE>::serialize
    //for serialization
    serialize_helper(_modelLayerData, ar, version);
}

template<typename Archive>
void ModelLayerData<_MODEL_LAYER_VERSION_ONE>::serialize(Archive & ar)
{
    ar & _xDimension;
    ar & _yDimension;
    ar & _zDimension;

    if (Archive::is_saving::value)
    {
        int dataType = static_cast<int>(_dataType);
        ar & dataType;
        size_t const totalSize = _xDimension*_yDimension*_zDimension;

        switch (_dataType)
        {
        case DataType::UCHAR:
            ar & boost::serialization::make_array<unsigned char>(_imageData.get(), totalSize);
            break;
        case DataType::USHORT:
            ar & boost::serialization::make_array<unsigned short>(_ushortImageData.get(), totalSize);
            break;
        default:
            std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
            throw ModelLayerException::InvalidDataException(message);
            break;
        }

        size_t subModelLayerCollectionSize = _subModelLayerCollection.size();
        ar & subModelLayerCollectionSize;
        //submodellayer
        for (auto const &key : _subModelLayerCollection)
        {
            SubModelLayer *subModelLayer = key.second.get();
            ar & subModelLayer; //saving is calling the correct serialization method in SubModelLayer
        }
    }
    if (Archive::is_loading::value) //loading
    {
        int dataType;
        ar & dataType;
        _dataType = static_cast<DataType>(dataType);
        try
        {
            size_t const totalSize = _xDimension*_yDimension*_zDimension;
            switch (_dataType)
            {
            case DataType::UCHAR:
                _imageData.reset(new unsigned char[totalSize]);
                ar & boost::serialization::make_array<unsigned char>(_imageData.get(), totalSize);
                break;
            case DataType::USHORT:
                _ushortImageData.reset(new unsigned short[totalSize]);
                ar & boost::serialization::make_array<unsigned short>(_ushortImageData.get(), totalSize);
                break;
            default:
                std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
                throw ModelLayerException::InvalidDataException(message);
                break;
            }
            int subModelLayerCollectionSize;
            ar & subModelLayerCollectionSize;
            for (size_t i = 0; i < subModelLayerCollectionSize; i++)
            {
                std::string timestamp;
                std::unique_ptr<SubModelLayer> subModelLayer;
                SubModelLayer * rawSubModelLayer = new SubModelLayer();
                //problem happens here
                ar & rawSubModelLayer; //loading is calling the wrong serialization method which is located in another class
                subModelLayer.reset(rawSubModelLayer);
                timestamp = subModelLayer->getTimestamp();
                _subModelLayerCollection.insert(std::map<std::string, std::unique_ptr<SubModelLayer>>::value_type(timestamp, std::move(subModelLayer)));
                switch (_dataType)
                {
                case DataType::UCHAR:
                    _subModelLayerCollection.at(timestamp)->setImageData(_imageData.get(), _xDimension, _yDimension, _zDimension);
                    break;
                case DataType::USHORT:
                    _subModelLayerCollection.at(timestamp)->setImageData(_ushortImageData.get(), _xDimension, _yDimension, _zDimension);
                    break;
                default:
                    std::string message = std::string(__FUNCTION__) + " | " + std::string(__FILE__);
                    throw ModelLayerException::InvalidDataException(message);
                    break;
                }
            }
        }
        catch (const std::exception& ex)
        {
            std::string message = std::string(ex.what()) + " " + std::string(__FUNCTION__) + " | " + std::string(__FILE__);
            throw ModelLayerException::AllocateImageDataException(message);
        }
    }
}
但是一个模仿我在coliru的类结构的小示例生成了包含类标识符的输出

更新:附加的子模型层标题和源以及子模型层数据源

SubModelLayer.hpp


您不应该显式地
new
正在反序列化的对象。指针序列化会自动处理它。请发布SubmodelLayer类的定义、其序列化函数和所有相关的注册宏。@n.m.我已附加了所需的源文件,但由于太多与序列化无关的不相关代码,我将其缩短了一点。@n.m.我没有尝试新建指针,然而,同样的错误也发生了。这并不是这个问题的原因,只是一些迹象表明,也许你没有完全理解这个东西是如何工作的<代码>应收和应付帐款在加载时修改
应付帐款
。你在里面的东西都会丢失。所以
ptr=something;ar&ptr
在加载时没有任何意义。@n.m.我仍然没有得到它。这是否意味着I
new
的对象在
ar&ptr
(内存泄漏)期间丢失,而语法实际上是实例化(
new()
)对象,然后将值写入其中?
22 serialization::archive 13 0 1 1
0 0 1 5.714890957e+000 -1.402821732e+001 1.363411617e+001 5.255104303e-001 1.317463517e-001 -1.736424565e-001 8.223928213e-001 1.000000000e+000 1.410727501e+001 2.772170639e+001 2.090770340e+001 7.853981853e-001 1 0 2 1 1
1 1 0 3 1 1
2 10 10 10 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 4 4 1 1
3 10 10 10 0 0 0 10 10 10 0 4
4 10 10 10 0 0 0 10 10 10 0 4
5 10 10 10 0 0 0 10 10 10 0 4
6 10 10 10 0 0 0 10 10 10 0 0 -1.00000000000000000e+000 1.00000000000000000e+000
//SubModelLayer.hpp    
static const unsigned _SUB_MODEL_LAYER_DATA_VERSION = 1;
    static const unsigned _SUB_MODEL_LAYER_DATA_CURRENT_VERSION = _SUB_MODEL_LAYER_DATA_VERSION;

template<unsigned version>
class SubModelLayerData;

template<>
class SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION> 
    : public Serializable, Setup
{
public:
    //No OIV object initialization should be done in constructor
    SubModelLayerData();
    ~SubModelLayerData();

    void setup();

    // Inherited via Serializable
    virtual void synchronize();

    template<typename Archive>
    void serialize(Archive & ar);

    int _xDimension;
    int _yDimension;
    int _zDimension;
    void *_data;
};

class SubModelLayer : public Node
{
public:
    SubModelLayer();
    ~SubModelLayer();
    // Inherited via Node
    virtual void synchronize() override;
    void setImageData(unsigned short * imageData, int const xDimension, int const yDimension, int const zDimension);
    void setImageData(unsigned char * imageData, int const xDimension, int const yDimension, int const zDimension);

private:
    friend class boost::serialization::access;
    template<typename Archive>
    void serialize(Archive & ar, const unsigned int version);

    // Inherited via Node
    virtual void setup() override;
    void renderSubModelLayer(int dataByteSize);

    //current version of sceneData
    SubModelLayerData<_SUB_MODEL_LAYER_DATA_CURRENT_VERSION> _subModelLayerData;
};

BOOST_CLASS_VERSION(SubModelLayer, _SUB_MODEL_LAYER_DATA_CURRENT_VERSION);
BOOST_CLASS_EXPORT_KEY(SubModelLayer);
//SubModelLayer.cpp
template void SubModelLayer::serialize(boost::archive::text_iarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::text_oarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::binary_iarchive & ar, const unsigned int version);
template void SubModelLayer::serialize(boost::archive::binary_oarchive & ar, const unsigned int version);


SubModelLayer::SubModelLayer()
    : Node(VArtObjectTypeID::SUBMODEL_LAYER)
{
    setup();
}

SubModelLayer::~SubModelLayer()
{
}

void SubModelLayer::setup()
{
    _subModelLayerData._root = getGroup();
    _subModelLayerData.setup();
    _subModelLayerData._root->setUserData(this);
}

template<typename Archive>
void SubModelLayer::serialize(Archive & ar, const unsigned int version)
{
    // invoke serialization of the base class
    ar & boost::serialization::base_object<Node>(*this);
    serialize_helper(_subModelLayerData, ar, version);
}

void SubModelLayer::synchronize()
{
    _subModelLayerData.synchronize();
}

void SubModelLayer::setImageData(unsigned short * imageData, int const xDimension, int const yDimension, int const zDimension)
{
    _subModelLayerData._data = imageData;
    _subModelLayerData._xDimension = xDimension;
    _subModelLayerData._yDimension = yDimension;
    _subModelLayerData._zDimension = zDimension;

    renderSubModelLayer(_UNSIGNED_SHORT_BYTE_SIZE);
}

void SubModelLayer::setImageData(unsigned char * imageData, int const xDimension, int const yDimension, int const zDimension)
{
    _subModelLayerData._data = imageData;
    _subModelLayerData._xDimension = xDimension;
    _subModelLayerData._yDimension = yDimension;
    _subModelLayerData._zDimension = zDimension;
    renderSubModelLayer(_UNSIGNED_CHAR_BYTE_SIZE);
}

BOOST_CLASS_EXPORT_IMPLEMENT(SubModelLayer);
//SubModelLayerData.cpp
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::text_iarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::text_oarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::binary_iarchive & ar);
template void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(boost::archive::binary_oarchive & ar);

SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::SubModelLayerData()
{
    _xDimension = 0;
    _yDimension = 0;
    _zDimension = 0;
}

template<typename Archive>
void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::serialize(Archive & ar)
{
    ar & _xDimension;
    ar & _yDimension;
    ar & _zDimension;
}

SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::~SubModelLayerData()
{
}

void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::synchronize()
{
}

void SubModelLayerData<_SUB_MODEL_LAYER_DATA_VERSION>::setup()
{
}
Scene * scene;
{
    std::ifstream file(projectName, std::ios::binary);
    boost::archive::binary_iarchive ia{ file };
    ia >> scene;
}
return scene;

{
    std::ofstream ofs(projectName, std::ios::binary);
    boost::archive::binary_oarchive binaryArchive(ofs);
    binaryArchive << scene;
}
template<class Tptr>
static void invoke(Archive & ar, Tptr & t){
    check_load(*t);
    const basic_pointer_iserializer * bpis_ptr = register_type(ar, *t);
    const basic_pointer_iserializer * newbpis_ptr = ar.load_pointer(
        // note major hack here !!!
        // I tried every way to convert Tptr &t (where Tptr might
        // include const) to void * &.  This is the only way
        // I could make it work. RR
        (void * & )t,
        bpis_ptr,
        find
    );
    // if the pointer isn't that of the base class
    if(newbpis_ptr != bpis_ptr){
        t = pointer_tweak(newbpis_ptr->get_eti(), t, *t);
    }
}