如何在c++中对派生类使用Boost序列化

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

本文关键字:Boost 序列化 派生 c++      更新时间:2023-10-16

我正在尝试使用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()生成一些虚拟数据,将其打印到标准输出,然后使用boost序列化将其保存。然后,它尝试从文件中读取数据并打印结果。它可以很好地保存数据,并且我可以打开数据文件并确认数据确实存在。

但是,当重新构建派生类(以及重新构建基类的实例)时,它会在基类的serialize()函数开始时失败。任何想法吗?我想我做了一切正确的例子,从提供的增强网站。提前谢谢你。此外,我在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 h1> Derived.cpp h1> GenericSerializer.h h1> GenericSerializer.cpp h1> 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)

boost演示http://www.boost.org/doc/libs/1_42_0/libs/serialization/example/demo.cpp为我工作。您可以使用valgrind测试代码以确保在错误点之前没有内存错误吗?

我记得不久前我的老板在他的mac上也遇到了boost序列化的问题。问题是使用标准的iostreams。当我们修改代码使用boost iostreams时,它可以在他的mac上运行。

我们还没有深入研究这个问题,所以现在我只能建议你尝试同样的方法,看看它是否有效:

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

注:我还不能给问题添加评论,我们也不能在SO上发布PM用户…所以我把它写下来作为答案。

编辑:好的,我看到你也在Ubuntu上测试了…我应该更仔细地阅读。尽管如此,这可能是值得尝试的,如果它不工作,我将删除这个答案。