Hello Robert,
----- Original Message -----
From:
"Robert Ramey" <ramey@rrsd.com>
To:
<boost@lists.boost.org>
Sent:
Tuesday, July 02, 2002 8:39 PM
Subject: RE: [boost] serialization - request
for formal review
>
> The function delete_created_pointers
deletes the created pointers AND
restores
> the original contents of
the pointer that was assigned to. This
effectivily restores
>
pointer elements to their original state what ever that may be. I
don't
have your
> example, so I can't comment on your particular
case. So, if the object
one is trying
> to restore contains
unassigned pointers and load invokes an exception, and
>
delete_created_pointers is called, the pointers will be restored to
their
original
> unassigned state. This may cause problems
somewhere else but cannot be
> addressed from the serialization
module. I believe that
> deleting created pointers AND restoring the
original values of the changed
> pointer values will effectively address
all of these issues.
It looks like two replies (to me and Kostya
Altukhov) got mixed into a
single message. Anyway, I'll reply to my part
:)
I really hadn't noticed that you were restoring the values of
pointers.
However, I don't think that solves the problem. The solution
assumes
something about the pointer variable by which loading is performed.
Consider
this loading code:
//loading code of class C that has member
variable a_ of type A*.
A* a;
archive >>
a;
a_ = a;
If later a crash occurs, the system will
attempt to modify the value of the
_local variable_ a (causing undefined
behavior), whereas the a_ will remain
the same and will cause a double
deletion fault. This is a serious
limitation on the system for the following
reasons:
1. a_ might be a const A*. This prevents me from directly saying
archive >>
a_, so I have to use this practice. This is a very typical
case.
2. You will have problems implementing container persistence.
Actually, the
function that implements loading of vectors in your library
uses code very
similar to the above:
T t; // when T = A*,
archive
>> t;
c.push_back(t).
In particular, I believe this was the
reason of the crash
delete_created_pointers( ) in my case (note that the
crash occurs inside
this function).
3. For vector, you may be able to
fix it. For containers such as set, you
can't, restoration of pointer values
will crash them.
Below is the test I
use.
Regards,
-Vahan
----------------------------------------------
----------------------------------------------
#include
"boost/serialization.hpp"
#include <fstream>
using namespace
std;
//A holds a pointer to another A, but doesn't own the
pointer.
//objCount
class A
{
public:
A()
{
next_ = 0;
++objcount;
}
A(const A& a)
{
next_ = a.next_;
++objcount;
}
~A()
{
--objcount;
}
void save(boost::basic_oarchive
&ar) const
{
ar << next_;
}
void load(boost::basic_iarchive &ar, boost::version_type
file_version)
{
static int i =
0;
++i;
bool b =
false;
if(i == 2)
b =
true;
ar >> next_;
if(b)
throw 0;
}
static
boost::version_type version(){return 0;}
A* next_;
static int objcount;
};
int A::objcount = 0;
int
main()
{
std::vector<A*> vec;
A* a = new
A;
a->next_ = 0;
vec.push_back(a);
//fill
the vector with chained A's. The vector is assumed
//to own the
objects - we will destroy the objects through this vector.
int
i;
for(i = 1; i < 10; ++i)
{
a =
new A;
vec[i - 1]->next_ = a;
a->next_ = 0;
vec.push_back(a);
}
//output the vector
{
ofstream
file("e:/kuku.txt", ios_base::binary);
boost::boarchive
ar(file);
ar << vec;
}
//erase the objects
for(i = 0; i < vec.size();
++i)
delete vec[i];
vec.clear();
//read the vector back
{
ifstream
file("e:/ankap.txt", ios_base::binary);
boost::biarchive
ar(file);
try{
ar
>> vec;
}
catch(...)
{
ar.delete_created_pointers();
}
}
//delete the objects
for(int i = 0; i < vec.size();
++i)
delete vec[i];
vec.clear();
//identify the leaks
int count =
A::objcount;
return 0;
}