|
Boost : |
From: George A. Heintzelman (georgeh_at_[hidden])
Date: 2002-02-27 17:23:11
> 2) The key used to detect duplicates is the pair <class id of the
> most derived class , address of the object> . So the scenario you
> describe [ serializing, deleting, recreating differently, serializing ] could produce suprises.
> In practice I wouldn't think it
> would be a problem.The envisioned usage of the libary is to "take a
> snapshot" of the state of a group of objects (and thier relatives)
> and sometime later restore all the objects to the previous state.
Hmm. Yes, but. I am somewhat concerned because pool implementations are
likely to produce objects which have the same address as previously
existing ones of the same type, and I worry that some naivete' here may
lead someone to problems. I don't have a concrete example though,
except of course for deliberate sabotage.
More worrisome to me is trying to use a serialization library -- which
I see as a fairly fundamental piece -- to implement more complicated
functionality. For example, it seems natural to want to use a
serialization library under some persistence or object database
library. In such cases, saving and restoring pointers is a much more
complex issue, and I worry that your implementation could interfere. So
even if you have a default mechanism in place, perhaps a user ought to
be able to replace the mechanism?
> This presumes that the state of the objects doesn't change when an
> archive is being written or read. This implementation of the library
> makes this assumption. I havn't considered what would happen if this
> assumption didn't hold. In an attempt to enforce this assumption,
> all the class member save functions are marked const. This should
> prevent the data from being changed while being serialized.
The assumption is not an unreasonable one, though it needs to be
explicit in documentation. But I fear the constness of class member
save functions will help you little, if at all:
class Y;
class X {
scoped_ptr<Y> p;
};
Inside const member functions of X, *p is quite fair game. And this is
actually probably the more likely case for running into such troubles...
> 3) For the moment - set aside the question of references which
> involves some other issues. I believe your example is summarized in
> the following code:
Yes.
> class Composite
> {
> Element e;
> }
>
> class Composite2
> {
> Element *eptr;
> }
>
> main()
> {
> Composite c;
> Composite2 c2;
> c2.eptr = &c.e;
>
> // create archive
> ::boost::archive oa;
> oa << c;
> oa << c2;
>
> // .....
>
> // create input archive - deserialize in same sequence as above
> ::boost::iarchive ia
> ia >> c; // note: reversing order of two would create
> ia >> c2; // duplicate object of type element
> }
>
> I came upon this situation and after considering it concluded that it
> would never occur. Now I'm having second thoughts. I will look into
> this. My conjecture is that it is always possible to avoid such
> situations. If this true then I can look in to adding
> assertion/exception code to reveal when it occurs so it can be
> addressed.
I'm not sure it is that easy to avoid. It would probably be fairly
common to give out pointers/references to elements of a map which is a
data member, for example. I know that I do this frequently. If one were
writing from scratch, it might be possible to avoid, but to retrofit a
workaround onto an existing class seems like trouble.
I don't know if there is a good solution to this one, and it is
certainly a devilish detail. Unfortunately, it seems to involve data
members knowing whether they are members or not -- something that is
anathema to C++. Of course, one can always say 'don't do this', but
again I imagine that might be easier said than done...
George Heintzelman
georgeh_at_[hidden]
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk