Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to use Boost Serialization with derived classes in C++?
    primarykey
    data
    text
    <p>I am trying to use Boost's serialization functionality to serialize a derived class. My base class doesn't have different data members, so the derived class just has this serialize() function:</p> <pre><code>template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { ar &amp; boost::serialization::base_object&lt;Car&gt;(*this); } </code></pre> <p>Then the base class has this serialize() function:</p> <pre><code>template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { ar &amp; color; ar &amp; miles; ar &amp; model; ar &amp; doors; } </code></pre> <p>Adding this to the base class made no difference:</p> <pre><code>BOOST_SERIALIZATION_ASSUME_ABSTRACT(Car) </code></pre> <p>The program compiles just fine. The main() generates some dummy data, prints it to stdout, then saves it with boost serialization. Then it attempts to read the data from the file and print the results. It saves the data just fine, and I can open the data files and confirm that the data is in fact present.</p> <p>However, when rebuilding the derived class (and when also rebuilding an instance of the base class), it fails at the beginning of the serialize() function for the base class. Any thoughts? I think I did everything correctly from the example provided on the boost website. Thank you in advance. Also, I'm using GCC 4 on Mac OS X and the latest boost library (from source), and the sample program works fine with boost when not dealing with inheritance.</p> <p><strong>Update:</strong> I get the same problem when trying to run the sample code in the Boost documentation <a href="http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/tutorial.html#derivedclasses" rel="nofollow">http://www.boost.org/doc/libs/1_42_0/libs/serialization/doc/tutorial.html#derivedclasses</a>:</p> <pre><code>class bus_stop_corner: public bus_stop { friend class boost::serialization::access; friend ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop_corner &amp;bsc); template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { // serialize base class information ar &amp; boost::serialization::base_object&lt;bus_stop&gt;(*this); // Fails here ar &amp; street1; ar &amp; street2; } string street1; string street2; virtual string description() const { return street1 + " and " + street2; } public: bus_stop_corner(){} bus_stop_corner(const gps_position &amp; lat_, const gps_position &amp; long_, const string &amp; s1_, const string &amp; s2_): bus_stop(lat_, long_), street1(s1_), street2(s2_) {} }; </code></pre> <p>For <code>ar &amp; boost::serialization::base_object&lt;bus_stop&gt;(*this);</code> GDB says <code>EXC_BAD_ACCESS</code>.</p> <h1>Derived.h</h1> <pre><code>#ifndef BoostSerialization_Derived_h #define BoostSerialization_Derived_h // This is pretty much the same code from the Boost Serialization documentation! #include &lt;boost/serialization/access.hpp&gt; #include &lt;boost/serialization/base_object.hpp&gt; #include &lt;iostream&gt; #include &lt;string&gt; 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 &amp;gp) {this-&gt;degrees = gp.degrees; this-&gt;minutes = gp.minutes; this-&gt;seconds = gp.seconds;} template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { ar &amp; degrees; ar &amp; minutes; ar &amp; seconds; } }; class bus_stop { friend class boost::serialization::access; friend ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop &amp;bsc); template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { ar &amp; latitude; ar &amp; longitude; } protected: gps_position latitude; gps_position longitude; bus_stop(const gps_position &amp; lat_, const gps_position &amp; long_): latitude(lat_), longitude(long_) {} public: bus_stop(){} bus_stop(const bus_stop &amp;bs) {this-&gt;latitude = bs.latitude; this-&gt;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&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop_corner &amp;bsc); template&lt;class Archive&gt; void serialize(Archive &amp; ar, const unsigned int version) { // serialize base class information ar &amp; boost::serialization::base_object&lt;bus_stop&gt;(*this); ar &amp; street1; ar &amp; street2; } string street1; string street2; virtual string description() const { return street1 + " and " + street2; } public: bus_stop_corner(){} bus_stop_corner(const bus_stop_corner &amp;bsc) {this-&gt;street1 = bsc.street1; this-&gt;street2 = bsc.street2; this-&gt;latitude = bsc.latitude; this-&gt;longitude = bsc.longitude;} bus_stop_corner(const gps_position &amp; lat_, const gps_position &amp; long_, const string &amp; s1_, const string &amp; s2_): bus_stop(lat_, long_), street1(s1_), street2(s2_) {} }; ostream&amp; operator&lt;&lt;(ostream &amp;out, const gps_position &amp;gps); ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop &amp;bsc); ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop_corner &amp;bsc); void derivedClassTest(); void derivedClassSave(); void derivedClassLoad(); #endif </code></pre> <h1>Derived.cpp</h1> <pre><code>#include "Derived.h" #include "GenericSerializer.h" ostream&amp; operator&lt;&lt;(ostream &amp;out, const gps_position &amp;gps) { out &lt;&lt; gps.degrees &lt;&lt; " degrees " &lt;&lt; gps.minutes &lt;&lt; "\" " &lt;&lt; gps.seconds &lt;&lt; "'"; return out; } ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop &amp;bsc) { out &lt;&lt; "Bus stop at " &lt;&lt; bsc.latitude &lt;&lt; " and " &lt;&lt; bsc.longitude; return out; } ostream&amp; operator&lt;&lt;(ostream &amp;out, const bus_stop_corner &amp;bsc) { out &lt;&lt; "Bus stop at the corner of " &lt;&lt; bsc.street1 &lt;&lt; " and " &lt;&lt; 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 &lt;&lt; "Bus stop: " &lt;&lt; bsc &lt;&lt; endl; GenericSerializer&lt;bus_stop_corner&gt; serializer(bsc); serializer.save("bus_stop.dat"); } void derivedClassLoad() { GenericSerializer&lt;bus_stop_corner&gt; serializer("bus_stop.dat"); bus_stop_corner bsc = serializer.getData(); cout &lt;&lt; "Loaded bus stop: " &lt;&lt; bsc &lt;&lt; endl; } </code></pre> <h1>GenericSerializer.h</h1> <pre><code>#ifndef BoostSerialization_GenericSerializer_h #define BoostSerialization_GenericSerializer_h #include &lt;string&gt; using namespace std; template &lt;class Serializable&gt; class GenericSerializer { private: Serializable *data; public: GenericSerializer(const Serializable &amp;s); ~GenericSerializer(); void save(string filename); GenericSerializer(string filename); Serializable getData() const; void load(string filename); }; #include "GenericSerializer.cpp" #endif </code></pre> <h1>GenericSerializer.cpp</h1> <pre><code>//#define BINARY #include &lt;iostream&gt; #include &lt;fstream&gt; #ifdef BINARY #include &lt;boost/archive/binary_oarchive.hpp&gt; #include &lt;boost/archive/binary_iarchive.hpp&gt; #else #include &lt;boost/archive/text_oarchive.hpp&gt; #include &lt;boost/archive/text_iarchive.hpp&gt; #endif #include &lt;string&gt; #include "GenericSerializer.h" using namespace std; template &lt;class Serializable&gt; GenericSerializer&lt;Serializable&gt;::GenericSerializer(const Serializable &amp;s) { this-&gt;data = new Serializable(s); } template &lt;class Serializable&gt; GenericSerializer&lt;Serializable&gt;::~GenericSerializer() { delete this-&gt;data; } template &lt;class Serializable&gt; void GenericSerializer&lt;Serializable&gt;::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 &lt;&lt; *data; ofs.close(); } template &lt;class Serializable&gt; GenericSerializer&lt;Serializable&gt;::GenericSerializer(string filename) { this-&gt;load(filename); } template &lt;class Serializable&gt; Serializable GenericSerializer&lt;Serializable&gt;::getData() const { return *this-&gt;data; } template &lt;class Serializable&gt; void GenericSerializer&lt;Serializable&gt;::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 &gt;&gt; *data; } </code></pre> <h1>Output with GDB</h1> <pre><code>Bus stop: Bus stop at the corner of Str. A and ul. B Program received signal SIGSEGV, Segmentation fault. 0x00007ffff78fcf04 in std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;::resize(unsigned long, char) () from /usr/lib/libstdc++.so.6 (gdb) bt #0 0x00007ffff78fcf04 in std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt;::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&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load (this=0x7fffffffdc60, s=...) at ./boost/archive/impl/basic_binary_iprimitive.ipp:111 #3 0x000000000040b9d8 in boost::archive::load_access::load_primitive&lt;boost::archive::binary_iarchive, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:107 #4 0x000000000040b73f in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::load_primitive::invoke&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:356 #5 0x000000000040b4f1 in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::invoke&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:433 #6 0x000000000040b07a in boost::archive::load&lt;boost::archive::binary_iarchive, std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; ( ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:580 #7 0x000000000040ad68 in boost::archive::detail::common_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/common_iarchive.hpp:68 #8 0x000000000040ab6f in boost::archive::basic_binary_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (this=0x7fffffffdc50, t=..., version=0) at /usr/include/boost/archive/basic_binary_iarchive.hpp:67 #9 0x000000000040a921 in boost::archive::binary_iarchive_impl&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load_override&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/binary_iarchive_impl.hpp:50 #10 0x000000000040a6c8 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&gt;&gt;&lt;std::basic_string&lt;char, std::char_traits&lt;char&gt;, std::allocator&lt;char&gt; &gt; &gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/interface_iarchive.hpp:61 #11 0x000000000040a445 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&amp;&lt;std::string&gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/interface_iarchive.hpp:68 #12 0x000000000040a107 in bus_stop_corner::serialize&lt;boost::archive::binary_iarchive&gt; (this=0x62d958, ar=..., version=0) at Derived.h:62 #13 0x0000000000409c5c in boost::serialization::access::serialize&lt;boost::archive::binary_iarchive, bus_stop_corner&gt; (ar=..., t=..., file_version=0) at /usr/include/boost/serialization/access.hpp:118 #14 0x000000000040994f in boost::serialization::serialize&lt;boost::archive::binary_iarchive, bus_stop_corner&gt; (ar=..., t=..., file_version=0) at /usr/include/boost/serialization/serialization.hpp:74 #15 0x0000000000409544 in boost::serialization::serialize_adl&lt;boost::archive::binary_iarchive, bus_stop_corner&gt; (ar=..., t=..., file_version=0) at /usr/include/boost/serialization/serialization.hpp:133 #16 0x0000000000408f12 in boost::archive::detail::iserializer&lt;boost::archive::binary_iarchive, bus_stop_corner&gt;::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=&lt;value optimized out&gt;, bis=...) at libs/serialization/src/basic_iarchive.cpp:399 #18 boost::archive::detail::basic_iarchive::load_object (this=0x7fffffffdc50, t=&lt;value optimized out&gt;, bis=...) at libs/serialization/src/basic_iarchive.cpp:547 #19 0x000000000040838a in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::load_standard::invoke&lt;bus_stop_corner&gt; (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:381 #20 0x0000000000408344 in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::invoke&lt;bus_stop_corner&gt; (ar=..., t=...) at /usr/include/boost/archive/detail/iserializer.hpp:433 #21 0x00000000004082dc in boost::archive::load&lt;boost::archive::binary_iarchive, bus_stop_corner&gt; (ar=..., t=...) ---Type &lt;return&gt; to continue, or q &lt;return&gt; to quit--- at /usr/include/boost/archive/detail/iserializer.hpp:580 #22 0x0000000000408288 in boost::archive::detail::common_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;bus_stop_corner&gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/common_iarchive.hpp:68 #23 0x0000000000408233 in boost::archive::basic_binary_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;bus_stop_corner&gt; (this=0x7fffffffdc50, t=..., version=0) at /usr/include/boost/archive/basic_binary_iarchive.hpp:67 #24 0x00000000004081d7 in boost::archive::binary_iarchive_impl&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load_override&lt;bus_stop_corner&gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/binary_iarchive_impl.hpp:50 #25 0x0000000000408150 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&gt;&gt;&lt;bus_stop_corner&gt; (this=0x7fffffffdc50, t=...) at /usr/include/boost/archive/detail/interface_iarchive.hpp:61 #26 0x0000000000407ff0 in GenericSerializer&lt;bus_stop_corner&gt;::load (this=0x7fffffffdf40, filename=...) at GenericSerializer.cpp:64 #27 0x0000000000407cff in GenericSerializer&lt;bus_stop_corner&gt;::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 </code></pre> <h1>bus_stop.dat (serialization output file)</h1> <pre><code>22 serialization::archive 7 0 0 0 0 0 0 1 2 3.3 4 5 6.6599998 6 Str. A 5 ul. B </code></pre> <h1>gcc -v -H</h1> <h2>On Mac OS X</h2> <pre><code>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) </code></pre> <h2>On Ubuntu</h2> <pre><code>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) </code></pre>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload