[英]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
。
#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
#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;
}
#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
//#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;
}
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
22 serialization::archive 7 0 0 0 0 0 0 1 2 3.3 4 5 6.6599998 6 Str. A 5 ul. B
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)
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.