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.