Boost logo

Boost :

From: Sergey Skorniakov (s.skorniakov_at_[hidden])
Date: 2007-03-23 04:07:53


Hi. I am found that if object,
1) loaded via pointer
2) throws exception in its constructor, while loadind
then destructor for this object will be erroneously called

Test code:

#define BOOST_SERIALIZATION_DYN_LINK
#include <boost/archive/polymorphic_iarchive.hpp>
#include <boost/archive/polymorphic_oarchive.hpp>
#include <boost/archive/polymorphic_xml_iarchive.hpp>
#include <boost/archive/polymorphic_xml_oarchive.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/export.hpp>
#include <sstream>
#include <iostream>
struct A
{
    int * p_;
    A() : p_(new int(10)) {}
    ~A()
    {
        std::cout << *p_;
        delete p_;
    }
    template <class Ar> void serialize(Ar & ar, const unsigned int file_version)
    {
        ar & boost::serialization::make_nvp("p", *p_);
    }
};
struct B
{
    A x_;
    int z_;
    B(int z) : z_(z) {}
    B()
    {
        throw std::runtime_error("test");
    }
    template <class Ar> void serialize(Ar & ar, const unsigned int file_version)
    {
        ar & BOOST_SERIALIZATION_NVP(z_);
        ar & BOOST_SERIALIZATION_NVP(x_);
    }
};
int main(int argc, char* argv[])
{
    try
    {
        std::stringstream s;
    {
        B b(0);
        B *pb = &b;
        b.z_ = 5;
        boost::archive::polymorphic_xml_oarchive ar(s);
        ar & BOOST_SERIALIZATION_NVP(pb);
    }
    {
        B *pb;
        boost::archive::polymorphic_xml_iarchive ar(s);
        ar & BOOST_SERIALIZATION_NVP(pb);
        delete pb;
    }
    } catch (std::runtime_error&)
    {}
    return 0;
}

Tested with boost 1.33.1 on MSVC 8. Member variable B::x_ deleted twice. I see strange piece of code in boost\archive\detail\iserializer.hpp:

    // catch exception during load_construct_data so that we don't
    // automatically delete the t which is most likely not fully
    // constructed
    BOOST_TRY {
        // this addresses an obscure situtation that occurs when
        // load_constructor de-serializes something through a pointer.
        ar.next_object_pointer(t);
        boost::serialization::load_construct_data_adl<Archive, T>(
            ar_impl,
            t,
            file_version
        );
    }
    BOOST_CATCH(...){
        BOOST_RETHROW;
    }
    BOOST_CATCH_END

Its look like that operator delete(ap.release()); or other code that detaches ap missing before BOOST_RETHROW. I had not tested my sample with current CVS version, but had not found any changes in this code and suppose that this error still persists.


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk