
On Fri, May 11, 2012 at 2:06 AM, Robert Ramey <ramey@rrsd.com> wrote:
Nikolay Mladenov wrote:
Hi Robert,
I remember that in the past the serialization library was throwing unsupported_class_version exception when reading of archives with future class versions. This no longer seems to be the case. We had older version of software crash when reading newer archive.
The only place that I found to mention unsupported_class_version is commented out and I do not understand the attached note:
BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( basic_iarchive & ar, void *x, const unsigned int file_version ) const { // note: we now comment this out. Before we permited archive // version # to be very large. Now we don't. To permit // readers of these old archives, we have to suppress this // code. Perhaps in the future we might re-enable it but // permit its suppression with a runtime switch. #if 0 // trap case where the program cannot handle the current version if(file_version > static_cast<const unsigned int>(version())) boost::serialization::throw_exception( archive::archive_exception(
boost::archive::archive_exception::unsupported_class_version, get_debug_info() ) ); #endif // make sure call is routed through the higest interface that might // be specialized by the user. boost::serialization::serialize_adl( boost::serialization::smart_cast_reference<Archive &>(ar), * static_cast<T *>(x), file_version ); }
To allow class to read serialized objects of newer version by default seems very dangerous. I generally requires extra work from the class author and without it will most likely crash.
So isn't it better to have an additional trait that a class author needs to define, if a class should be allowed read future versions?
something like
namespace boost{ namespace serialization { template<class T> struct allow_future_versions : mpl::false_ {}; }}
#define BOOST_SERIALIZATION_ALLOW_FUTURE_VERSIONS(T) \ namespace boost{ namespace serialization \ { \ template<> struct allow_future_versions<T> : mpl::true_ {}; \ }}
and change the code above to:
BOOST_DLLEXPORT void iserializer<Archive, T>::load_object_data( basic_iarchive & ar, void *x, const unsigned int file_version ) const { // trap case where the program cannot handle the current version if( ! boost::serialization::allow_future_versions<T>::value && file_version > static_cast<const unsigned int>(version())) boost::serialization::throw_exception( archive::archive_exception(
boost::archive::archive_exception::unsupported_class_version, get_debug_info() ) );
......
Your right about this and your proposal is a worthy one though I think there's a simpler way to do it.. I'll look into this.
As to why it's this way, the answer is pretty simple. The original version of the library has some errors. Problem is, fixing them is much harder than with other libraries because of the requirement to maintain the ability to read archives created with previous versions.
I am not sure how to understand this. The commented out code checks for future versions, not for previous versions?
Robert Ramey
Thanks in advance,
Nikolay Mladenov Sitius Automation Inc.
If I am to avoid the crash when reading future version I seem to have 2 options: 1) add a check in every load/serialize function and throw when future version is detected 2) add the same check but in the fuction or functions that call the load/serialize functions My problem with 1 is that there are many calls that need to be fixed, plus a new guideline is needed for future serializable classes. Not to mention that this problem applies to other people and companies (https://svn.boost.org/trac/boost/ticket/6856) And my problem with 2 is that I have to mess up with the serialization library which I am not so familiar with. Nikolay Mladenov Sitius Automation Inc.