Boost C++ Libraries: Ticket #5789: Segmentation fault with serialization when register_type rearranged https://svn.boost.org/trac10/ticket/5789 <p> In our project we use boost-serialization to store objects by base-class pointer (boost::shared_ptr). We choose to register polymorphic classes by register_type method. So we have a template of a function which contains all class registrations like this: </p> <p> template &lt;class Archive&gt; void <a class="missing wiki">RegisterDerivedClasses</a>(Archive&amp; ar) { </p> <blockquote> <p> ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); <em> ... </em></p> </blockquote> <p> } </p> <p> This function template is called on each archive object before we use it. With development of the project we add new class registrations in this function template. </p> <p> The problem is a segmentation fault occuring in following situation: </p> <p> 1) our program serializes some data with boost-serialization 2) we add new class registration, so function <a class="missing wiki">RegisterDerivedClasses</a> changes to something like this: --- template &lt;class Archive&gt; void <a class="missing wiki">RegisterDerivedClasses</a>(Archive&amp; ar) { </p> <blockquote> <p> ar.register_type((<a class="missing wiki">NewClass</a>*)0); </p> </blockquote> <blockquote> <p> ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); <em> ... </em></p> </blockquote> <p> } --- 3) we recompile our project to produce the program 4) the program deserializes data produced in step 1 (no change in serialize methods) </p> <p> ================================================================================= </p> <p> BOST VERSION AND BUILD: </p> <p> This is occuring with Boost 1.47 and we checked this is occuring as well with 1.45. </p> <p> Our boost library is prepared with following steps: </p> <p> ./bootstrap.sh --with-libraries=date_time,filesystem,serialization,system,thread,signals --prefix=/usr/local/boost/1.47 ./b2 --layout=system variant=release link=static threading=multi </p> <p> ================================================================================= </p> <p> OS PLATFORM: Ubuntu 10.10, "uname -a" gives: </p> <p> Linux raU 2.6.38-10-generic-pae <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/44" title="#44: Bugs: regex_match bidirectional-iterator bug (closed: Fixed)">#44</a>~lucid1-Ubuntu SMP Mon Jun 6 22:01:00 UTC 2011 i686 GNU/Linux </p> <p> ================================================================================= </p> <p> GCC: "g++ -v" gives: </p> <p> Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.5.1/lto-wrapper Target: i686-linux-gnu Configured with: ../src/configure -v --with-pkgversion='<a class="missing wiki">Ubuntu/Linaro</a> 4.5.1-7ubuntu2' --with-bugurl=<a class="ext-link" href="file:///usr/share/doc/gcc-4.5/README.Bugs"><span class="icon">​</span>file:///usr/share/doc/gcc-4.5/README.Bugs</a> --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --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.5 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --with-plugin-ld=ld.gold --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu Thread model: posix gcc version 4.5.1 (<a class="missing wiki">Ubuntu/Linaro</a> 4.5.1-7ubuntu2) </p> <p> ================================================================================= </p> <p> Compilation of the sample program: </p> <p> g++ test20.cpp -I /usr/local/boost/1.47/include/ -L /usr/local/boost/1.47/lib/ -lboost_serialization </p> <p> Running sample program: </p> <p> ./a.out </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/5789 Trac 1.4.3 Krzysztof Tomaszewski <kt@…> Tue, 16 Aug 2011 19:09:06 GMT attachment set https://svn.boost.org/trac10/ticket/5789 https://svn.boost.org/trac10/ticket/5789 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test20.cpp</span> </li> </ul> <p> Sample program causing segmentation fault </p> Ticket Krzysztof Tomaszewski <kt@…> Tue, 16 Aug 2011 19:12:54 GMT <link>https://svn.boost.org/trac10/ticket/5789#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5789#comment:1</guid> <description> <p> GDB shows following back-trace (after compiled with -g): </p> <pre class="wiki">Program received signal SIGSEGV, Segmentation fault. 0x080575d6 in boost::archive::detail::basic_iarchive::load_pointer(void*&amp;, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&amp;)) () (gdb) bt #0 0x080575d6 in boost::archive::detail::basic_iarchive::load_pointer(void*&amp;, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&amp;)) () #1 0x0805370c in boost::archive::detail::load_pointer_type&lt;boost::archive::binary_iarchive&gt;::invoke&lt;A*&gt; (ar=..., t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:524 #2 0x0805367d in boost::archive::load&lt;boost::archive::binary_iarchive, A*&gt; (ar=..., t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592 #3 0x0805361a in boost::archive::detail::common_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;A*&gt; (this=0xbffff46c, t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/detail/common_iarchive.hpp:66 #4 0x080535b3 in boost::archive::basic_binary_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;A*&gt; (this=0xbffff46c, t=@0xbffff09c, version=0) at /usr/local/boost/1.47/include/boost/archive/basic_binary_iarchive.hpp:70 #5 0x080534ca in boost::archive::binary_iarchive_impl&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load_override&lt;A*&gt; (this=0xbffff46c, t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/binary_iarchive_impl.hpp:50 #6 0x080533b2 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&gt;&gt;&lt;A*&gt; (this=0xbffff46c, t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:60 #7 0x080532e4 in boost::serialization::nvp&lt;A*&gt;::load&lt;boost::archive::binary_iarchive&gt; (this=0xbffff074, ar=...) at /usr/local/boost/1.47/include/boost/serialization/nvp.hpp:87 #8 0x0805321a in boost::serialization::access::member_load&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/access.hpp:101 #9 0x08053151 in boost::serialization::detail::member_loader&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt;::invoke (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/split_member.hpp:54 #10 0x08053088 in boost::serialization::split_member&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/split_member.hpp:69 #11 0x08052f5d in boost::serialization::nvp&lt;A*&gt;::serialize&lt;boost::archive::binary_iarchive&gt; (this=0xbffff074, ar=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/nvp.hpp:89 #12 0x08052ce4 in boost::serialization::access::serialize&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/access.hpp:118 #13 0x080529eb in boost::serialization::serialize&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/serialization.hpp:69 #14 0x0805285c in boost::serialization::serialize_adl&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=..., file_version=0) at /usr/local/boost/1.47/include/boost/serialization/serialization.hpp:128 #15 0x0805257f in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::load_only::invoke&lt;boost::serialization::nvp&lt;A*&gt; &gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:373 #16 0x08051f28 in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::invoke&lt;boost::serialization::nvp&lt;A*&gt; const&gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:439 #17 0x080517ca in boost::archive::load&lt;boost::archive::binary_iarchive, boost::serialization::nvp&lt;A*&gt; const&gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592 #18 0x0805115a in boost::archive::detail::common_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;boost::serialization::nvp&lt;A*&gt; const&gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/detail/common_iarchive.hpp:66 #19 0x08050a5b in boost::archive::basic_binary_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;boost::serialization::nvp&lt;A*&gt; const&gt; (this=0xbffff46c, t=..., version=0) at /usr/local/boost/1.47/include/boost/archive/basic_binary_iarchive.hpp:70 #20 0x08050224 in boost::archive::binary_iarchive_impl&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load_override&lt;boost::serialization::nvp&lt;A*&gt; const&gt; ( this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/binary_iarchive_impl.hpp:50 #21 0x0804fad4 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&gt;&gt;&lt;boost::serialization::nvp&lt;A*&gt; const&gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:60 #22 0x0804f670 in boost::serialization::load&lt;boost::archive::binary_iarchive, A&gt; (ar=..., t=..., file_version=1) at /usr/local/boost/1.47/include/boost/serialization/shared_ptr.hpp:137 #23 0x0804f0ea in boost::serialization::free_loader&lt;boost::archive::binary_iarchive, boost::shared_ptr&lt;A&gt; &gt;::invoke (ar=..., t=..., file_version=1) at /usr/local/boost/1.47/include/boost/serialization/split_free.hpp:58 #24 0x0804e958 in boost::serialization::split_free&lt;boost::archive::binary_iarchive, boost::shared_ptr&lt;A&gt; &gt; (ar=..., t=..., file_version=1) at /usr/local/boost/1.47/include/boost/serialization/split_free.hpp:74 #25 0x0804e55d in boost::serialization::serialize&lt;boost::archive::binary_iarchive, A&gt; (ar=..., t=..., file_version=1) at /usr/local/boost/1.47/include/boost/serialization/shared_ptr.hpp:171 #26 0x0804dcac in boost::serialization::serialize_adl&lt;boost::archive::binary_iarchive, boost::shared_ptr&lt;A&gt; &gt; (ar=..., t=..., file_version=1) at /usr/local/boost/1.47/include/boost/serialization/serialization.hpp:128 #27 0x0804d2aa in boost::archive::detail::iserializer&lt;boost::archive::binary_iarchive, boost::shared_ptr&lt;A&gt; &gt;::load_object_data (this=0x807c6ac, ar=..., x=0xbffff48c, file_version=1) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:188 #28 0x080573a9 in boost::archive::detail::basic_iarchive::load_object(void*, boost::archive::detail::basic_iserializer const&amp;) () #29 0x0804cb2f in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::load_standard::invoke&lt;boost::shared_ptr&lt;A&gt; &gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:387 #30 0x0804caba in boost::archive::detail::load_non_pointer_type&lt;boost::archive::binary_iarchive&gt;::invoke&lt;boost::shared_ptr&lt;A&gt; &gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:439 #31 0x0804c468 in boost::archive::load&lt;boost::archive::binary_iarchive, boost::shared_ptr&lt;A&gt; &gt; (ar=..., t=...) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592 ---Type &lt;return&gt; to continue, or q &lt;return&gt; to quit--- #32 0x0804bfb2 in boost::archive::detail::common_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;boost::shared_ptr&lt;A&gt; &gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/detail/common_iarchive.hpp:66 #33 0x0804bea5 in boost::archive::basic_binary_iarchive&lt;boost::archive::binary_iarchive&gt;::load_override&lt;boost::shared_ptr&lt;A&gt; &gt; (this=0xbffff46c, t=..., version=0) at /usr/local/boost/1.47/include/boost/archive/basic_binary_iarchive.hpp:70 #34 0x0804ba8a in boost::archive::binary_iarchive_impl&lt;boost::archive::binary_iarchive, char, std::char_traits&lt;char&gt; &gt;::load_override&lt;boost::shared_ptr&lt;A&gt; &gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/binary_iarchive_impl.hpp:50 #35 0x0804b694 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&gt;&gt;&lt;boost::shared_ptr&lt;A&gt; &gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:60 #36 0x0804b4f2 in boost::archive::detail::interface_iarchive&lt;boost::archive::binary_iarchive&gt;::operator&amp;&lt;boost::shared_ptr&lt;A&gt; &gt; (this=0xbffff46c, t=...) at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:67 #37 0x0804a00b in main () at test20.cpp:85 </pre> </description> <category>Ticket</category> </item> <item> <author>Krzysztof Tomaszewski <kt@…></author> <pubDate>Tue, 16 Aug 2011 19:25:54 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5789#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5789#comment:2</guid> <description> <p> Sorry for lack of proper formatting - here with formating: </p> <hr /> <p> In our project we use boost-serialization to store objects by base-class pointer (boost::shared_ptr). We choose to register polymorphic classes by register_type method. So we have a template of a function which contains all class registrations like this: </p> <pre class="wiki">template &lt;class Archive&gt; void RegisterDerivedClasses(Archive&amp; ar) { ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); //... } </pre><p> This function template is called on each archive object before we use it. With development of the project we add new class registrations in this function template. </p> <p> The problem is a segmentation fault occuring in following situation: </p> <ol><li>our program serializes some data with boost-serialization </li><li>we add new class registration, so function <a class="missing wiki">RegisterDerivedClasses</a> changes to something like this: <pre class="wiki">template &lt;class Archive&gt; void RegisterDerivedClasses(Archive&amp; ar) { ar.register_type((NewClass?*)0); ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); //... } </pre></li><li>we recompile our project to produce the program </li><li>the program tries to deserializes data produced in step 1 (no change in serialize methods) - <strong>HERE SEG-FAULT OCCURS</strong> </li></ol><p> ================================================================================= </p> <p> BOST VERSION AND BUILD: </p> <p> This is occuring with Boost 1.47 and we checked this is occuring as well with 1.45. </p> <p> Our boost library is prepared with following steps: </p> <pre class="wiki">./bootstrap.sh --with-libraries=date_time,filesystem,serialization,system,thread,signals --prefix=/usr/local/boost/1.47 ./b2 --layout=system variant=release link=static threading=multi </pre><p> ================================================================================= </p> <p> OS PLATFORM: Ubuntu 10.10, "uname -a" gives: </p> <p> Linux raU 2.6.38-10-generic-pae <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/44" title="#44: Bugs: regex_match bidirectional-iterator bug (closed: Fixed)">#44</a>~lucid1-Ubuntu SMP Mon Jun 6 22:01:00 UTC 2011 i686 GNU/Linux </p> <p> ================================================================================= </p> <p> GCC: "g++ -v" gives: </p> <p> Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/i686-linux-gnu/4.5.1/lto-wrapper Target: i686-linux-gnu Configured with: ../src/configure -v --with-pkgversion='<a class="missing wiki">Ubuntu/Linaro</a>? 4.5.1-7ubuntu2' --with-bugurl= <a class="ext-link" href="file:///usr/share/doc/gcc-4.5/README.Bugs"><span class="icon">​</span>file:///usr/share/doc/gcc-4.5/README.Bugs</a> --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.5 --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.5 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-plugin --enable-gold --with-plugin-ld=ld.gold --enable-objc-gc --enable-targets=all --disable-werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=i686-linux-gnu --host=i686-linux-gnu --target=i686-linux-gnu Thread model: posix gcc version 4.5.1 (<a class="missing wiki">Ubuntu/Linaro</a>? 4.5.1-7ubuntu2) </p> <p> ================================================================================= </p> <p> Compilation of the sample program: </p> <p> g++ test20.cpp -I /usr/local/boost/1.47/include/ -L /usr/local/boost/1.47/lib/ -lboost_serialization </p> <p> Running sample program: </p> <p> ./a.out </p> </description> <category>Ticket</category> </item> <item> <author>Krzysztof Tomaszewski <kt@…></author> <pubDate>Wed, 17 Aug 2011 10:28:11 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/5789#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/5789#comment:3</guid> <description> <p> The best solution would be as follows: </p> <ul><li>archive content created by archive object with registered classes A, B, C should be correctly readable by archive object with registered classes A, B, C, <strong>D</strong> - thus adding new class (D) registration at the end without change of order of registration of previously registered classes (A, B, C) should not break ability to read archive contents created when class D was not registered </li></ul><ul><li>or register_type method should allow to give class name in form of <strong>const char*</strong> or <strong>std::string</strong> - such solution would allow to register classes in any order - archive content will be readable as far as all needed classes are registered in archive object </li></ul><ul><li>lack of required class registration needed to read archive content must be signaled by <strong>exception</strong> thus no segmentation fault occurs. </li></ul> </description> <category>Ticket</category> </item> <item> <dc:creator>Robert Ramey</dc:creator> <pubDate>Sun, 15 Jul 2012 20:49:28 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/5789#comment:4 https://svn.boost.org/trac10/ticket/5789#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">invalid</span> </li> </ul> <p> If I understand your problem correctly </p> <p> "1) our program serializes some data with boost-serialization 2) we add new class registration, so function <a class="missing wiki">RegisterDerivedClasses</a>? changes to something like this: --- template &lt;class Archive&gt; void <a class="missing wiki">RegisterDerivedClasses</a>?(Archive&amp; ar) {" </p> <p> I think the answer is the following: </p> <p> a) using the "registration method" adds data to the archive. b) adding another "registration method" adds more data to the archive. c) problem occurs when reading previously saved data with new program. </p> <p> and the solution is: </p> <p> a) remember that using the "registration method" is really no different then adding any kind of new data to the archive definition. b) adding any new data required using class versioning to keep things in sync. c) If you implement class versioning - I believe this will address this problem. </p> <p> I think I'm correct on this, so I'm going to close this item for now. </p> <p> Robert Ramey </p> <p> Robert Ramey </p> Ticket