Boost logo

Boost Users :

From: Tim Taylor (tim_at_[hidden])
Date: 2006-06-09 13:17:32


Hi,

I am having some troubles with serialization of shared_ptrs. The basic
problem is that when I serialize a shared_ptr, then later deserialize
into a new shared_ptr, the use_count of the new pointer is, incorrectly
(as far as I can see), 2 rather than 1.

I am using boost 1.33.1 and gcc 4.0.1.

Here is some example code to demonstrate the problem:

-----
// compile with:
// gcc -o ptrser-test ptrser-test.cpp -lstdc++ -lboost_serialization-gcc

#include <iostream>
#include <fstream>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/shared_ptr.hpp>

using namespace std;
using namespace boost;

class Item
{
public:
   // Constructors/destructor--------------------------
   Item(int n = 0)
   : _n(n) {
     cout << "In Item constructor" << endl;
   };

   Item(const Item& other) {
     cout << "In Item copy constructor" << endl;
     _n = other._n;
   };

   ~Item() {
     cout << "In Item destructor" << endl;
   };

   // Data members-------------------------------------
   int _n;

   // Methods------------------------------------------
   friend class boost::serialization::access;

   template<class Archive>
   void serialize(Archive& ar, const unsigned int version) {
     ar & _n;
   }
};

class Bag
{
public:
   // Constructors/destructor--------------------------
   Bag() {
     cout << "In Bag default constructor" << endl;
   };

   Bag(shared_ptr<Item> item)
   : _item(item) {
     cout << "In Bag shared_ptr constructor" << endl;
   };

   Bag(const Bag& other) {
     cout << "In Bag copy constructor" << endl;
     _item = other._item;
   };

   ~Bag() {
     cout << "In Bag destructor" << endl;
   };

   // Data members-------------------------------------
   shared_ptr<Item> _item;

   // Methods------------------------------------------
   void printUseCount() const {
     cout << "Use count: " << _item.use_count() << endl;
   }

   friend class boost::serialization::access;

   template<class Archive>
   void serialize(Archive& ar, const unsigned int version) {
     ar & _item;
   }
};

int main(int argc, char **argv)
{
   const char *filename = "bag.ser";

   // create a Bag object with a new Item in it
   Bag *pBag = new Bag(shared_ptr<Item>(new Item(1)));

   // now serialize the Bag
   cout << "About to serialize bag..." << endl;
   ofstream osSer(filename);
   boost::archive::text_oarchive oa(osSer);
   const Bag& constBag = *pBag;
   oa << constBag;
   osSer.close();

   pBag->printUseCount();

   // delete the original Bag
   cout << "About to delete bag 1..." << endl;
   delete pBag;

   // create a new Bag object
   cout << "About to create a new bag..." << endl;
   pBag = new Bag;

   pBag->printUseCount();

   // and deserialize it into the new Bag object
   cout << "About to deserialize bag..." << endl;
   ifstream isSer(filename, std::ios::binary);
   boost::archive::text_iarchive ia(isSer);
   ia >> *pBag;
   isSer.close();

   pBag->printUseCount();

   // delete the second BSag
   cout << "About to delete bag 2..." << endl;
   delete pBag;

   return 0;
}
-----

This code produces the following output:

-----
In Item constructor
In Bag shared_ptr constructor
About to serialize bag...
Use count: 1
About to delete bag 1...
In Bag destructor
In Item destructor
About to create a new bag...
In Bag default constructor
Use count: 0
About to deserialize bag...
In Item constructor
Use count: 2
About to delete bag 2...
In Bag destructor
In Item destructor
-----

The series of constructor and destructor calls is as expected. After
the first Bag object is created with a shared_ptr to an Item in it, the
use_count of the shared_ptr is 1. When the first Bag object (including
the shared_ptr) are deleted, and a new, empty Bag object created, the
use_count is now (as expected) 0. However, when the serialization
archive is deserialized into the new Bag object, the use_count of the
shared_ptr jumps from 0 to 2.

Am I doing something silly here, or is this a bug in the shared_ptr
serialization code?

For interest, the saved archive (bag.ser) produced by this code looks
like this:

-----
22 serialization::archive 3 0 0 0 1 2 1 0
0 1
-----

Any help would be much appreciated.

Tim


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net