Opened 11 years ago

Closed 10 years ago

#5789 closed Bugs (invalid)

Segmentation fault with serialization when register_type rearranged

Reported by: Krzysztof Tomaszewski <kt@…> Owned by: Robert Ramey
Milestone: To Be Determined Component: serialization
Version: Boost 1.47.0 Severity: Problem
Keywords: Cc:

Description

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:

template <class Archive> void RegisterDerivedClasses(Archive& ar) {

ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); ...

}

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.

The problem is a segmentation fault occuring in following situation:

1) our program serializes some data with boost-serialization 2) we add new class registration, so function RegisterDerivedClasses changes to something like this: --- template <class Archive> void RegisterDerivedClasses(Archive& ar) {

ar.register_type((NewClass*)0);

ar.register_type((A*)0); ar.register_type((B*)0); ar.register_type((C*)0); ...

} --- 3) we recompile our project to produce the program 4) the program deserializes data produced in step 1 (no change in serialize methods)

=================================================================================

BOST VERSION AND BUILD:

This is occuring with Boost 1.47 and we checked this is occuring as well with 1.45.

Our boost library is prepared with following steps:

./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

=================================================================================

OS PLATFORM: Ubuntu 10.10, "uname -a" gives:

Linux raU 2.6.38-10-generic-pae #44~lucid1-Ubuntu SMP Mon Jun 6 22:01:00 UTC 2011 i686 GNU/Linux

=================================================================================

GCC: "g++ -v" gives:

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='Ubuntu/Linaro 4.5.1-7ubuntu2' --with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs --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 (Ubuntu/Linaro 4.5.1-7ubuntu2)

=================================================================================

Compilation of the sample program:

g++ test20.cpp -I /usr/local/boost/1.47/include/ -L /usr/local/boost/1.47/lib/ -lboost_serialization

Running sample program:

./a.out

Attachments (1)

test20.cpp (1.6 KB ) - added by Krzysztof Tomaszewski <kt@…> 11 years ago.
Sample program causing segmentation fault

Download all attachments as: .zip

Change History (5)

by Krzysztof Tomaszewski <kt@…>, 11 years ago

Attachment: test20.cpp added

Sample program causing segmentation fault

comment:1 by Krzysztof Tomaszewski <kt@…>, 11 years ago

GDB shows following back-trace (after compiled with -g):

Program received signal SIGSEGV, Segmentation fault.
0x080575d6 in boost::archive::detail::basic_iarchive::load_pointer(void*&, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&)) ()
(gdb) bt
#0  0x080575d6 in boost::archive::detail::basic_iarchive::load_pointer(void*&, boost::archive::detail::basic_pointer_iserializer const*, boost::archive::detail::basic_pointer_iserializer const* (*)(boost::serialization::extended_type_info const&)) ()
#1  0x0805370c in boost::archive::detail::load_pointer_type<boost::archive::binary_iarchive>::invoke<A*> (ar=..., t=@0xbffff09c)
    at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:524
#2  0x0805367d in boost::archive::load<boost::archive::binary_iarchive, A*> (ar=..., t=@0xbffff09c) at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592
#3  0x0805361a in boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::load_override<A*> (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<boost::archive::binary_iarchive>::load_override<A*> (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<boost::archive::binary_iarchive, char, std::char_traits<char> >::load_override<A*> (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<boost::archive::binary_iarchive>::operator>><A*> (this=0xbffff46c, t=@0xbffff09c)
    at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:60
#7  0x080532e4 in boost::serialization::nvp<A*>::load<boost::archive::binary_iarchive> (this=0xbffff074, ar=...) at /usr/local/boost/1.47/include/boost/serialization/nvp.hpp:87
#8  0x0805321a in boost::serialization::access::member_load<boost::archive::binary_iarchive, boost::serialization::nvp<A*> > (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<boost::archive::binary_iarchive, boost::serialization::nvp<A*> >::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<boost::archive::binary_iarchive, boost::serialization::nvp<A*> > (ar=..., t=..., file_version=0)
    at /usr/local/boost/1.47/include/boost/serialization/split_member.hpp:69
#11 0x08052f5d in boost::serialization::nvp<A*>::serialize<boost::archive::binary_iarchive> (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<boost::archive::binary_iarchive, boost::serialization::nvp<A*> > (ar=..., t=..., file_version=0)
    at /usr/local/boost/1.47/include/boost/serialization/access.hpp:118
#13 0x080529eb in boost::serialization::serialize<boost::archive::binary_iarchive, boost::serialization::nvp<A*> > (ar=..., t=..., file_version=0)
    at /usr/local/boost/1.47/include/boost/serialization/serialization.hpp:69
#14 0x0805285c in boost::serialization::serialize_adl<boost::archive::binary_iarchive, boost::serialization::nvp<A*> > (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<boost::archive::binary_iarchive>::load_only::invoke<boost::serialization::nvp<A*> > (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<boost::archive::binary_iarchive>::invoke<boost::serialization::nvp<A*> const> (ar=..., t=...)
    at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:439
#17 0x080517ca in boost::archive::load<boost::archive::binary_iarchive, boost::serialization::nvp<A*> const> (ar=..., t=...)
    at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592
#18 0x0805115a in boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::load_override<boost::serialization::nvp<A*> const> (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<boost::archive::binary_iarchive>::load_override<boost::serialization::nvp<A*> const> (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<boost::archive::binary_iarchive, char, std::char_traits<char> >::load_override<boost::serialization::nvp<A*> const> (
    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<boost::archive::binary_iarchive>::operator>><boost::serialization::nvp<A*> const> (this=0xbffff46c, t=...)
    at /usr/local/boost/1.47/include/boost/archive/detail/interface_iarchive.hpp:60
#22 0x0804f670 in boost::serialization::load<boost::archive::binary_iarchive, A> (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<boost::archive::binary_iarchive, boost::shared_ptr<A> >::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<boost::archive::binary_iarchive, boost::shared_ptr<A> > (ar=..., t=..., file_version=1)
    at /usr/local/boost/1.47/include/boost/serialization/split_free.hpp:74
#25 0x0804e55d in boost::serialization::serialize<boost::archive::binary_iarchive, A> (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<boost::archive::binary_iarchive, boost::shared_ptr<A> > (ar=..., t=..., file_version=1)
    at /usr/local/boost/1.47/include/boost/serialization/serialization.hpp:128
#27 0x0804d2aa in boost::archive::detail::iserializer<boost::archive::binary_iarchive, boost::shared_ptr<A> >::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&) ()
#29 0x0804cb2f in boost::archive::detail::load_non_pointer_type<boost::archive::binary_iarchive>::load_standard::invoke<boost::shared_ptr<A> > (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<boost::archive::binary_iarchive>::invoke<boost::shared_ptr<A> > (ar=..., t=...)
    at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:439
#31 0x0804c468 in boost::archive::load<boost::archive::binary_iarchive, boost::shared_ptr<A> > (ar=..., t=...)
    at /usr/local/boost/1.47/include/boost/archive/detail/iserializer.hpp:592
---Type <return> to continue, or q <return> to quit---
#32 0x0804bfb2 in boost::archive::detail::common_iarchive<boost::archive::binary_iarchive>::load_override<boost::shared_ptr<A> > (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<boost::archive::binary_iarchive>::load_override<boost::shared_ptr<A> > (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<boost::archive::binary_iarchive, char, std::char_traits<char> >::load_override<boost::shared_ptr<A> > (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<boost::archive::binary_iarchive>::operator>><boost::shared_ptr<A> > (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<boost::archive::binary_iarchive>::operator&<boost::shared_ptr<A> > (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

comment:2 by Krzysztof Tomaszewski <kt@…>, 11 years ago

Sorry for lack of proper formatting - here with formating:


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:

template <class Archive> 
void RegisterDerivedClasses(Archive& ar) {
    ar.register_type((A*)0);
    ar.register_type((B*)0);
    ar.register_type((C*)0);
    //...
}

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.

The problem is a segmentation fault occuring in following situation:

  1. our program serializes some data with boost-serialization
  2. we add new class registration, so function RegisterDerivedClasses changes to something like this:
    template <class Archive>
    void RegisterDerivedClasses(Archive& ar) {
    
        ar.register_type((NewClass?*)0);
    
        ar.register_type((A*)0);
        ar.register_type((B*)0);
        ar.register_type((C*)0);
        //...
    }
    
  3. we recompile our project to produce the program
  4. the program tries to deserializes data produced in step 1 (no change in serialize methods) - HERE SEG-FAULT OCCURS

=================================================================================

BOST VERSION AND BUILD:

This is occuring with Boost 1.47 and we checked this is occuring as well with 1.45.

Our boost library is prepared with following steps:

./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

=================================================================================

OS PLATFORM: Ubuntu 10.10, "uname -a" gives:

Linux raU 2.6.38-10-generic-pae #44~lucid1-Ubuntu SMP Mon Jun 6 22:01:00 UTC 2011 i686 GNU/Linux

=================================================================================

GCC: "g++ -v" gives:

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='Ubuntu/Linaro? 4.5.1-7ubuntu2' --with-bugurl= file:///usr/share/doc/gcc-4.5/README.Bugs --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 (Ubuntu/Linaro? 4.5.1-7ubuntu2)

=================================================================================

Compilation of the sample program:

g++ test20.cpp -I /usr/local/boost/1.47/include/ -L /usr/local/boost/1.47/lib/ -lboost_serialization

Running sample program:

./a.out

comment:3 by Krzysztof Tomaszewski <kt@…>, 11 years ago

The best solution would be as follows:

  • 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, D - 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
  • or register_type method should allow to give class name in form of const char* or std::string - 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
  • lack of required class registration needed to read archive content must be signaled by exception thus no segmentation fault occurs.

comment:4 by Robert Ramey, 10 years ago

Resolution: invalid
Status: newclosed

If I understand your problem correctly

"1) our program serializes some data with boost-serialization 2) we add new class registration, so function RegisterDerivedClasses? changes to something like this: --- template <class Archive> void RegisterDerivedClasses?(Archive& ar) {"

I think the answer is the following:

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.

and the solution is:

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.

I think I'm correct on this, so I'm going to close this item for now.

Robert Ramey

Robert Ramey

Note: See TracTickets for help on using tickets.