Я пытаюсь использовать функцию сериализации 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 () генерирует некоторые фиктивные данные, печатает их на стандартный вывод, а затем сохраняет их с расширенной сериализацией. Затем он пытается прочитать данные из файла и распечатать результаты. Он прекрасно сохраняет данные, и я могу открыть файлы данных и подтвердить, что данные действительно присутствуют.
Однако при перестройке производного класса (а также при перестроении экземпляра базового класса) происходит сбой в начале функции serialize () для базового класса. Какие-нибудь мысли? Я думаю, что я все сделал правильно из примера, представленного на сайте Boost. Заранее спасибо. Кроме того, я использую GCC 4 в Mac OS X и последнюю версию библиотеки 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)