Re: [Boost-users] [boost.serialization] serialization crash
I've had the same problems. The problem is with the bool field. Code restoring the archive crashes if the bool stored in the archive is not equal to 0 or 1. But since you did not write a constructor in the Obj class, the boolean will actually be initialized with anything( eg, read 14675002 for example), and will be serialized that way in the archive since it seems the serialization code does not check if the bool is equal to 0 or 1 (only the restoration code).
So, the solution is to initialize your boolean correctly and be very careful whenever you use booleans. However, I think the Serialization code should be fixed (remove the check for 0 or 1, it probably does more bad than good.
Jean-Noël
________________________________
De : boost-users-bounces@lists.boost.org [mailto:boost-users-bounces@lists.boost.org] De la part de Pavlo Korzhyk
Envoyé : jeudi 26 octobre 2006 16:09
À : boost-users@lists.boost.org
Objet : [Boost-users] [boost.serialization] serialization crash
The following code crashes under cygwin+boost1.33 and under mingw+boost1.33
I create text archive in a file, and then serialization crashes when restoring object from that archive.
The problem seem to be with bool field, if I replace
bool x;
with
int x;
in the class Obj implementation, everything runs fine.
Is this a bug in serialization code?
#include <iostream>
#include <sstream>
#include <fstream>
#include <vector>
#include <map>
using namespace std;
#include
RIVASSEAU Jean Noel wrote:
I've had the same problems. The problem is with the bool field. Code restoring the archive crashes if the bool stored in the archive is not equal to 0 or 1. But since you did not write a constructor in the Obj class, the boolean will actually be initialized with anything( eg, read 14675002 for example), and will be serialized that way in the archive since it seems the serialization code does not check if the bool is equal to 0 or 1 (only the restoration code).
So, the solution is to initialize your boolean correctly and be very careful whenever you use booleans. However, I think the Serialization code should be fixed (remove the check for 0 or 1, it probably does more bad than good.
In my (very) humble opinion, it should be at least symmetric. So either no check for 0 or 1 in both directions or a check for 0 or 1 in both directions. But it should also be consistent with other built-in types. Since it appears that there is no check (is one even possible?) for uninitialized data with other built-in types, I also vote for no check.
You guys are barking up the wrong tree. This behavior is handled by the stream implementation NOT the serialization library itself. It is exactly the same case as for floats. In this case, floats which are NaN can be written to a stream but not read back. Same for bools. There has been work in trying to make a portable implementation of stream input/output of varying types of NaN's. This has been hampered by the fact that the handling of NaN's varies accross implementation so it doesn't seem possible to make "transportable" archives which can be guarenteed to recover the same type of NaN that has been saved. For what it's worth, my personal view is that the attempt to save an undefined value - be it a NaN, undefined bool or whatever should be considered an error and trapped as soon as possible. Implementing this would be fairly easy with a custom stream facet which can be optionally attached to any stream. This would leave the choice as to what behavior he desires in the hands of the user. But no one has been motivated to actually do this so far. Robert Ramey Deane Yang wrote:
RIVASSEAU Jean Noel wrote:
I've had the same problems. The problem is with the bool field. Code restoring the archive crashes if the bool stored in the archive is not equal to 0 or 1. But since you did not write a constructor in the Obj class, the boolean will actually be initialized with anything( eg, read 14675002 for example), and will be serialized that way in the archive since it seems the serialization code does not check if the bool is equal to 0 or 1 (only the restoration code).
So, the solution is to initialize your boolean correctly and be very careful whenever you use booleans. However, I think the Serialization code should be fixed (remove the check for 0 or 1, it probably does more bad than good.
In my (very) humble opinion, it should be at least symmetric. So either no check for 0 or 1 in both directions or a check for 0 or 1 in both directions.
But it should also be consistent with other built-in types. Since it appears that there is no check (is one even possible?) for uninitialized data with other built-in types, I also vote for no check.
Robert Ramey wrote:
There has been work in trying to make a portable implementation of stream input/output of varying types of NaN's. This has been hampered by the fact that the handling of NaN's varies accross implementation so it doesn't seem possible to make "transportable" archives which can be guarenteed to recover the same type of NaN that has been saved.
For what it's worth, my personal view is that the attempt to save an undefined value - be it a NaN, undefined bool or whatever should be considered an error and trapped as soon as possible. Implementing this would be fairly easy with a custom stream facet which can be optionally attached to any stream. This would leave the choice as to what behavior he desires in the hands of the user.
But no one has been motivated to actually do this so far.
I'm working on such facets still for handling non-finite floating point numbers (infinity and NaN). I have code that works fine for float and double, but there are still some problems to be resolved for long double. And yes, the code has a facility for trapping infinity and NaN, if you so wish. --Johan
Johan Råde wrote:
But no one has been motivated to actually do this so far.
I'm working on such facets still for handling non-finite floating point numbers (infinity and NaN). I have code that works fine for float and double, but there are still some problems to be resolved for long double. And yes, the code has a facility for trapping infinity and NaN, if you so wish.
--Johan
Sorry, I should have mentioned this. I had thought that the idea of trapping the undefined behavior was abandoned for lack of interest. I'm glad to see I was wrong about this. I looks like you might want to include bools in this as well. As I recall, part of the problem with "trapping" was which exception to throw. Maybe this might be best handled the way other stream errors are handled - but setting a status flag and requiring that the user check it. As you can see, this is a recurring topic. I believe it will be helpful to serialization, lexical_cast and perhaps others. Also it may appeal to those of us programmers with slightly "paranoid" personalities who are convinced that everyone else is out to catch us. Robert Ramey
Robert Ramey wrote:
Johan Råde wrote:
But no one has been motivated to actually do this so far. I'm working on such facets still for handling non-finite floating point numbers. Sorry, I should have mentioned this. I had thought that the idea of trapping the undefined behavior was abandoned for lack of interest.
There was no lack of interest. You were interested, and that suffices.
I'm glad to see I was wrong about this. I looks like you might want to include bools in this as well.
That would be trivial, just a few lines of code. (IMHO serializing an initialized bool is a very very bad idea, but if it is of use to anyone, why not allow it to be done safely.) All that is needed is a facet derived from std::num_put with a virtual function like this: ... my_num_put::do_put(..., bool b) { if(b) b = true; else b = false; std::num_put::do_put(..., b); } This will replace an uninitialized bool with an unspecified initialized bool, before serializing it. I will add this to nonfinite_num_put. I do not believe it is possible to detect and trap an uninitialized bool.
As I recall, part of the problem with "trapping" was which exception to throw. Maybe this might be best handled the way other stream errors are handled - by setting a status flag and requiring that the user check it.
The problem is that the formatting facets (such as std::num_put and facets derived from std::num_put) do not have access to the the stream state. Only parsing facets (such as std::num_get and facets derived from std::num_get) have access to the stream state. It seems that the designers of the IOStreams library assumed that formatting always succeeds. I believe they made a design error here. The best solution I could think of was to have the facet throw an exception. This leads to unspecified behaviour: 1. the exception may propagate through the stream object, 2. the stream may catch the exception and rethrow it 3. the stream may catch the exception and throw another exception 4. the steram may catch the exception and set the failbit 5. the stream may catch the exception and set the badbit But dealing with this is not too bad, as long as you are aware of it.
As you can see, this is a recurring topic. I believe it will be helpful to serialization, lexical_cast and perhaps others. Also it may appeal to those of us programmers with slightly "paranoid" personalities who are convinced that everyone else is out to catch us.
The current status of the project is that I need robust and portable isnan, signbit, and changesign functions. I'm pursuing an approach based on examining the bit-patterns of the numbers. It all works, except for long double on Itanium processors. I'm investigating that problem. John Maddock is also working on these functions. Stay tuned. --Johan
participants (4)
-
Deane Yang
-
Johan Råde
-
RIVASSEAU Jean Noel
-
Robert Ramey