簡體   English   中英

如何在C ++中使用派生類進行Boost序列化?

[英]How to use Boost Serialization with derived classes in C++?

我試圖使用Boost的序列化功能來序列化派生類。 我的基類沒有不同的數據成員,因此派生類只有這個serialize()函數:

template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
    ar & boost::serialization::base_object<Car>(*this);
}

然后基類有這個serialize()函數:

template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
    ar & color;
    ar & miles;
    ar & model;
    ar & doors;
}

將其添加到基類沒有任何區別:

BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car)

該程序編譯得很好。 main()生成一些虛擬數據,將其打印到stdout,然后使用boost序列化保存它。 然后它嘗試從文件中讀取數據並打印結果。 它可以很好地保存數據,我可以打開數據文件並確認數據實際存在。

但是,在重建派生類時(以及重建基類的實例時),它在基類的serialize()函數的開頭失敗。 有什么想法嗎? 我想我從boost網站上提供的示例中做了一切正確的事情。 先感謝您。 另外,我在Mac OS X上使用GCC 4和最新的boost庫(來自源代碼),並且在不處理繼承時,示例程序可以正常使用boost。

更新:嘗試在Boost文檔中運行示例代碼時遇到同樣的問題http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/tutorial.html#derivedclasses

class bus_stop_corner: public bus_stop {
friend class boost::serialization::access;
friend ostream& operator<<(ostream &out, const bus_stop_corner &bsc);
template<class Archive>
void serialize(Archive & ar, const unsigned int version) {
    // serialize base class information
    ar & boost::serialization::base_object<bus_stop>(*this); // Fails here
    ar & street1;
    ar & street2;
}
string street1;
string street2;
virtual string description() const {
    return street1 + " and " + street2;
}
public:
bus_stop_corner(){}
bus_stop_corner(const gps_position & lat_, const gps_position & long_, const string & s1_, const string & s2_): bus_stop(lat_, long_), street1(s1_), street2(s2_) {}
};

對於ar & boost::serialization::base_object<bus_stop>(*this); GDB說EXC_BAD_ACCESS

Derived.h

#ifndef BoostSerialization_Derived_h
#define BoostSerialization_Derived_h
// This is pretty much the same code from the Boost Serialization documentation!
#include <boost/serialization/access.hpp>
#include <boost/serialization/base_object.hpp>
#include <iostream>
#include <string>
using namespace std;

class gps_position {
public:
    int degrees;
    int minutes;
    float seconds;
    gps_position(){};
    gps_position(int d, int m, float s):degrees(d), minutes(m), seconds(s) {}
    gps_position(const gps_position &gp) {this->degrees = gp.degrees; this->minutes = gp.minutes; this->seconds = gp.seconds;}
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & degrees;
        ar & minutes;
        ar & seconds;
    }
};

class bus_stop {
    friend class boost::serialization::access;
    friend ostream& operator<<(ostream &out, const bus_stop &bsc);
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        ar & latitude;
        ar & longitude;
    }
protected:
    gps_position latitude;
    gps_position longitude;
    bus_stop(const gps_position & lat_, const gps_position & long_): latitude(lat_),   longitude(long_) {}
public:
    bus_stop(){}
    bus_stop(const bus_stop &bs) {this->latitude = bs.latitude; this->longitude = bs.longitude;}
    // See item # 14 in Effective C++ by Scott Meyers.
    // re non-virtual destructors in base classes.
    virtual ~bus_stop(){}
};

class bus_stop_corner: public bus_stop {
    friend class boost::serialization::access;
    friend ostream& operator<<(ostream &out, const bus_stop_corner &bsc);
    template<class Archive>
    void serialize(Archive & ar, const unsigned int version) {
        // serialize base class information
        ar & boost::serialization::base_object<bus_stop>(*this);
        ar & street1;
        ar & street2;
    }
    string street1;
    string street2;
    virtual string description() const {
        return street1 + " and " + street2;
    }
public:
    bus_stop_corner(){}
    bus_stop_corner(const bus_stop_corner &bsc) {this->street1 = bsc.street1; this->street2 = bsc.street2; this->latitude = bsc.latitude; this->longitude = bsc.longitude;}
    bus_stop_corner(const gps_position & lat_, const gps_position & long_, const string & s1_, const string & s2_): bus_stop(lat_, long_), street1(s1_), street2(s2_) {}
};

ostream& operator<<(ostream &out, const gps_position &gps);
ostream& operator<<(ostream &out, const bus_stop &bsc);
ostream& operator<<(ostream &out, const bus_stop_corner &bsc);

void derivedClassTest();
void derivedClassSave();
void derivedClassLoad();
#endif

Derived.cpp

#include "Derived.h"
#include "GenericSerializer.h"

ostream& operator<<(ostream &out, const gps_position &gps) {
    out << gps.degrees << " degrees " << gps.minutes << "\" " << gps.seconds << "'";
    return out;
}

ostream& operator<<(ostream &out, const bus_stop &bsc) {
    out << "Bus stop at " << bsc.latitude << " and " << bsc.longitude;
    return out;
}

ostream& operator<<(ostream &out, const bus_stop_corner &bsc) {
    out << "Bus stop at the corner of " << bsc.street1 << " and " << bsc.street2;
    return out;
}

void derivedClassTest() {
    derivedClassSave();
    derivedClassLoad();
}

void derivedClassSave() {
    gps_position lat;
    gps_position lng;

    lat.degrees = 1;
    lat.minutes = 2;
    lat.seconds = 3.3;

    lng.degrees = 4;
    lng.minutes = 5;
    lng.seconds = 6.66;

    bus_stop_corner bsc(lat, lng, "Str. A", "ul. B");

    cout << "Bus stop: " << bsc << endl;

    GenericSerializer<bus_stop_corner> serializer(bsc);
    serializer.save("bus_stop.dat");
}

void derivedClassLoad() {
    GenericSerializer<bus_stop_corner> serializer("bus_stop.dat");
    bus_stop_corner bsc = serializer.getData();

    cout << "Loaded bus stop: " << bsc << endl;
}

GenericSerializer.h

#ifndef BoostSerialization_GenericSerializer_h
#define BoostSerialization_GenericSerializer_h

#include <string>
using namespace std;

template <class Serializable>
class GenericSerializer {
private:
    Serializable *data;

public:
    GenericSerializer(const Serializable &s);
    ~GenericSerializer();
    void save(string filename);

    GenericSerializer(string filename);
    Serializable getData() const;
    void load(string filename);
};

#include "GenericSerializer.cpp"

#endif

GenericSerializer.cpp

//#define BINARY

#include <iostream>
#include <fstream>
#ifdef BINARY
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#else
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#endif
#include <string>
#include "GenericSerializer.h"
using namespace std;

template <class Serializable>
GenericSerializer<Serializable>::GenericSerializer(const Serializable &s) {
    this->data = new Serializable(s);
}

template <class Serializable>
GenericSerializer<Serializable>::~GenericSerializer() {
    delete this->data;
}

template <class Serializable>
void GenericSerializer<Serializable>::save(string filename) {
    ofstream ofs(filename.c_str(), ios::binary);
#ifdef BINARY
    boost::archive::binary_oarchive oa(ofs, boost::archive::no_header);
#else
    boost::archive::text_oarchive oa(ofs);
#endif
    oa << *data;
    ofs.close();
}

template <class Serializable>
GenericSerializer<Serializable>::GenericSerializer(string filename) {
    this->load(filename);
}

template <class Serializable>
Serializable GenericSerializer<Serializable>::getData() const {
    return *this->data;
}

template <class Serializable>
void GenericSerializer<Serializable>::load(string filename) {
    ifstream ifs(filename.c_str(), ios::binary);
#ifdef BINARY
    boost::archive::binary_iarchive ia(ifs, boost::archive::no_header);
#else
    boost::archive::text_iarchive ia(ifs);
#endif
    ia >> *data; 
}

用GDB輸出

Bus stop: Bus stop at the corner of Str. A and ul. B

Program received signal SIGSEGV, Segmentation fault. 0x00007ffff78fcf04 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::resize(unsigned long, char) () from /usr/lib/libstdc++.so.6
(gdb) bt
#0  0x00007ffff78fcf04 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::resize(unsigned long, char) () from /usr/lib/libstdc++.so.6
#1  0x00007ffff7ba395f in resize (this=0x7fffffffdc60, s=...) at /usr/include/c++/4.4/bits/basic_string.h:667
#2  boost::archive::basic_binary_iprimitive<boost::archive::binary_iarchive, char, std::char_traits<char> >::load (this=0x7fffffffdc60, s=...)
    at ./boost/archive/impl/basic_binary_iprimitive.ipp:111
#3  0x000000000040b9d8 in boost::archive::load_access::load_primitive<boost::archive::binary_iarchive, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
> (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:107
#4  0x000000000040b73f in boost::archive::detail::load_non_pointer_type<boost::archive::binary_iarchive>::load_primitive::invoke<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:356
#5  0x000000000040b4f1 in boost::archive::detail::load_non_pointer_type<boost::archive::binary_iarchive>::invoke<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:433
#6  0x000000000040b07a in boost::archive::load<boost::archive::binary_iarchive, std::basic_string<char, std::char_traits<char>, std::allocator<char> >
> (
    ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:580
#7  0x000000000040ad68 in boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::load_override<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/common_iarchive.hpp:68
#8  0x000000000040ab6f in boost::archive::basic_binary_iarchive<boost::archive::binary_iarchive>::load_override<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (this=0x7fffffffdc50, t=..., version=0) at /usr/include/boost/archive/basic_binary_iarchive.hpp:67
#9  0x000000000040a921 in boost::archive::binary_iarchive_impl<boost::archive::binary_iarchive, char, std::char_traits<char> >::load_override<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/binary_iarchive_impl.hpp:50
#10 0x000000000040a6c8 in boost::archive::detail::interface_iarchive<boost::archive::binary_iarchive>::operator>><std::basic_string<char, std::char_traits<char>, std::allocator<char> > > (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/interface_iarchive.hpp:61
#11 0x000000000040a445 in boost::archive::detail::interface_iarchive<boost::archive::binary_iarchive>::operator&<std::string> (this=0x7fffffffdc50, t=...)
    at /usr/include/boost/archive/detail/interface_iarchive.hpp:68
#12 0x000000000040a107 in bus_stop_corner::serialize<boost::archive::binary_iarchive> (this=0x62d958, ar=..., version=0) at Derived.h:62
#13 0x0000000000409c5c in boost::serialization::access::serialize<boost::archive::binary_iarchive, bus_stop_corner> (ar=..., t=..., file_version=0)
    at /usr/include/boost/serialization/access.hpp:118
#14 0x000000000040994f in boost::serialization::serialize<boost::archive::binary_iarchive, bus_stop_corner> (ar=..., t=..., file_version=0)
    at /usr/include/boost/serialization/serialization.hpp:74
#15 0x0000000000409544 in boost::serialization::serialize_adl<boost::archive::binary_iarchive, bus_stop_corner> (ar=..., t=..., file_version=0)
    at /usr/include/boost/serialization/serialization.hpp:133
#16 0x0000000000408f12 in boost::archive::detail::iserializer<boost::archive::binary_iarchive, bus_stop_corner>::load_object_data (this=0x62aa30, ar=..., 
    x=0x62d958, file_version=0) at /usr/include/boost/archive/detail/iserializer.hpp:182
#17 0x00007ffff7b9b857 in load_object (this=0x7fffffffdc50, t=<value optimized out>, bis=...) at libs/serialization/src/basic_iarchive.cpp:399
#18 boost::archive::detail::basic_iarchive::load_object (this=0x7fffffffdc50, t=<value optimized out>, bis=...)
    at libs/serialization/src/basic_iarchive.cpp:547
#19 0x000000000040838a in boost::archive::detail::load_non_pointer_type<boost::archive::binary_iarchive>::load_standard::invoke<bus_stop_corner> (ar=..., 
    t=...) at /usr/include/boost/archive/detail/iserializer.hpp:381
#20 0x0000000000408344 in boost::archive::detail::load_non_pointer_type<boost::archive::binary_iarchive>::invoke<bus_stop_corner> (ar=..., t=...)
    at /usr/include/boost/archive/detail/iserializer.hpp:433
#21 0x00000000004082dc in boost::archive::load<boost::archive::binary_iarchive, bus_stop_corner> (ar=..., t=...)
---Type <return> to continue, or q <return> to quit---
    at /usr/include/boost/archive/detail/iserializer.hpp:580
#22 0x0000000000408288 in boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::load_override<bus_stop_corner> (this=0x7fffffffdc50, 
    t=...) at /usr/include/boost/archive/detail/common_iarchive.hpp:68
#23 0x0000000000408233 in boost::archive::basic_binary_iarchive<boost::archive::binary_iarchive>::load_override<bus_stop_corner> (this=0x7fffffffdc50, t=..., 
    version=0) at /usr/include/boost/archive/basic_binary_iarchive.hpp:67
#24 0x00000000004081d7 in boost::archive::binary_iarchive_impl<boost::archive::binary_iarchive, char, std::char_traits<char> >::load_override<bus_stop_corner>
    (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/binary_iarchive_impl.hpp:50
#25 0x0000000000408150 in boost::archive::detail::interface_iarchive<boost::archive::binary_iarchive>::operator>><bus_stop_corner> (this=0x7fffffffdc50, 
    t=...) at /usr/include/boost/archive/detail/interface_iarchive.hpp:61
#26 0x0000000000407ff0 in GenericSerializer<bus_stop_corner>::load (this=0x7fffffffdf40, filename=...) at GenericSerializer.cpp:64
#27 0x0000000000407cff in GenericSerializer<bus_stop_corner>::GenericSerializer (this=0x7fffffffdf40, filename=...) at GenericSerializer.cpp:48
#28 0x00000000004063f1 in derivedClassLoad () at Derived.cpp:53
#29 0x00000000004060f9 in derivedClassTest () at Derived.cpp:29
#30 0x000000000040fcf7 in main (argc=1, argv=0x7fffffffe2b8) at main.cpp:44

bus_stop.dat(序列化輸出文件)

22 serialization::archive 7 0 0 0 0 0 0 1 2 3.3 4 5 6.6599998 6 Str. A 5 ul. B

gcc -v -H

在Mac OS X上

Using built-in specs.
Target: i686-apple-darwin11
Configured with: /private/var/tmp/llvmgcc42/llvmgcc42-2335.15~25/src/configure --disable-checking --enable-werror --prefix=/Developer/usr/llvm-gcc-4.2 --mandir=/share/man --enable-languages=c,objc,c++,obj-c++ --program-prefix=llvm- --program-transform-name=/^[cg][^.-]*$/s/$/-4.2/ --with-slibdir=/usr/lib --build=i686-apple-darwin11 --enable-llvm=/private/var/tmp/llvmgcc42/llvmgcc42-2335.15~25/dst-llvmCore/Developer/usr/local --program-prefix=i686-apple-darwin11- --host=x86_64-apple-darwin11 --target=i686-apple-darwin11 --with-gxx-include-dir=/usr/include/c++/4.2.1
Thread model: posix
gcc version 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2335.15.00)

在Ubuntu上

Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.4.4-14ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.4.5 (Ubuntu/Linaro 4.4.4-14ubuntu5)

增強演示http://www.boost.org/doc/libs/1_42_0/libs/serialization/example/demo.cpp為我工作。 你能用valgrind測試你的代碼,以確保在被控制的點之前沒有內存錯誤嗎?

我記得不久前我的老板也在他的mac上提升序列化問題。 問題在於使用標准的iostream。 當我們更改代碼以使用boost iostreams時,它正在使用他的mac。

我們還沒有深入挖掘這個問題,所以目前我只能建議你嘗試一下,看看它是否有效:

boost::iostreams::stream_buffer<boost::iostreams::file_sink> ofs( "filename" );

PS我還不能在問題上添加評論,而且我們不能讓PM用戶參與...所以我把它寫成答案。

編輯:好的,我看到你也在Ubuntu上測試了......我應該仔細閱讀。 不過,這可能值得嘗試,如果它不起作用我會刪除這個答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM