Opened 11 years ago
Closed 10 years ago
#5789 closed Bugs (invalid)
Segmentation fault with serialization when register_type rearranged
Reported by: | 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)
Change History (5)
by , 11 years ago
Attachment: | test20.cpp added |
---|
comment:1 by , 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 , 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:
- our program serializes some data with boost-serialization
- 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); //... }
- we recompile our project to produce the program
- 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 , 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 , 10 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
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
Sample program causing segmentation fault