[Serialization] archive_exception from bad interaction serialization() and load_construct_data()
In short, combining a class implementation of serialize() with load/save_construct_data as described in the docs writes and reads data twice.
Varying the pattern can produce exceptions. My solution is to implement serialize() as a no-op and provide paired load/save_construct_data() functions. Is that actually a solution? Is there a better way?
The code at the bottom of this message yields
Microsoft C++ exception: boost::archive::archive_exception at memory location 0x000000B8189AC300.
When attempting to read in what was just written out.
Debugging shows that code attempts to read in the object twice, first in the class-specific
load_construct_data function I wrote, and then again in the instance method A::serialize. Since the save operation only wrote it out once, there is nothing, or at least nothing expected, to read and things go badly.
The documentation (https://www.boost.org/doc/libs/1_76_0/libs/serialization/doc/serialization.h...) says "If there is no such default constructor, the function templates load_construct_data and perhaps save_construct_data will have to be overridden." "perhaps" seems to imply that it is not essential to do so, and since the lack of a default constructor only matters when materializing an object I only wrote a load_construct_data function.
The example in the documentation does show both a save_construct_data and a load_construct_data function and if I uncomment save_construct_data in the code below, it runs without error and reconstructs the object.
HOWEVER, this only works because the data are written out twice, and then read in twice. I think the problem is that
TestBed.exe!boost::archive::detail::pointer_iserializerboost::archive::text_iarchive,A::load_object_ptr(boost::archive::detail::basic_iarchive & ar, void * t, const unsigned int file_version) Line 340
at J:\Programs\boost_1_76_0\boost\archive\detail\iserializer.hpp(340)
first materializes the object and then--after it is already constructed--passes it off to
ar_impl >> boost::serialization::make_nvp(NULL, * static_cast
I wrote ------------------------------------------ Sent: Thursday, June 10, 2021 5:17 PM In short, combining a class implementation of serialize() with load/save_construct_data as described in the docs writes and reads data twice. Varying the pattern can produce exceptions. My solution is to implement serialize() as a no-op and provide paired load/save_construct_data() functions. Is that actually a solution? Is there a better way? ..... ----------------------------------------------- At least for the real problem, the "solution" did not work. First, I got errors about unknown types until I added a call to boost::serialization::base_object<MyBaseClass>(*this) in the otherwise empty method of the derived class. I tried other approaches to registering the relationship, but none worked. Second, even having done that I was unable to read in the serialized data. The problem is that the output file has more stuff in it than the input serialization expects. Here's the start, with offset on the far left, followed by hexadecimal representation and then plain text: 00000000: 3232 2073 6572 6961 6c69 7a61 7469 6f6e 22 serialization 00000010: 3a3a 6172 6368 6976 6520 3139 2030 2031 ::archive 19 0 1 00000020: 2030 0d0a 3020 3020 3020 3137 2043 003a 0..0 0 0 17 C.: The 17 at the end is a character count, with C: the start of the string using multibyte encoding. On input, the code starts looking for the character count several positions before the 17, ending up with a 0 count and sequencing problems that soon lead to an exception. The reading and writing code appears completely symmetric: the load and save_construct_data methods match; the serialization code is the same in both directions; both do register_type<MyDerivedClass>() on the archive just after creating the archive object and just before serialization; both execute the load/save_construct_data code before the class-based serialization code. My suspicion is that the "extra" stuff relates to the derived and base classes, although the register_type function didn't seem to generate I/O on output or input. After several days of debugging and experimenting I decided not to use the serialize library, at least with objects lacking a default constructor. Ross
participants (1)
-
Boylan, Ross