$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
Subject: Re: [boost] [Serialization] Bizarre bug
From: Jarl Lindrud (jarl.lindrud_at_[hidden])
Date: 2009-08-10 04:01:49
Robert Ramey <ramey <at> rrsd.com> writes:
> > -----------------------------------------
> >
> > * If one program writes archives like this:
> >
> >    ar & vec; // vec is a std::vector<char>
> >
> > , it is then impossible to reliably load that archive in another
> > program, unless one is aware of the entire compile-time content of
> > the first program.
> 
> Nope.  The only time a problem can occur if one does
> 
>     ar & vec; // vec is a std::vector<char>
> 
> In the saving program and
> 
>     ar & p_vec; // vec is a * std::vector<char>
> 
> in the loading progam. 
Robert, that's manifestly incorrect. I have appended 3 well-formed programs, 
A1, A2, and B, to this post. B can read archives from A1, but it *cannot* read 
archives from A2. If you don't believe me, then please run the programs 
yourself. The only difference between A1 and A2 is compile-time instantiation, 
of code that is never executed.
> 
> Making matters worse, the archive
> 
> > format change is compatibility- breaking.
> 
> Only for collections of primitives.
> 
So we do agree that compatibility does break, due to compile-time instantiation.
> 
> I would use "concievable" rather than "likely".  In fact, I can't think
> of any real program where this could occur without there being
> some other error that would also prevent this program from
> functioning.
> 
Do you consider there to be any errors in either A1, A2 or B?
If you were to implement a generic IPC marshalling layer, you would end up with 
the kind of code that A1, A2, and B contain. IPC serialization is a bit 
different from file-based serialization, in that serialization and 
deserialization generally take place in different programs.
Another wrinkle in IPC serialization, is that one program may contain only 
serialization code for a type T (and not deserialization), while another 
program may contain only deserialization code for type T (and not 
serialization). If that makes the programs ill-formed in your view, then I 
guess one would have to conclude that B.Ser. is not an appropriate choice for 
IPC applications.
Regards,
Jarl
----------------------------------
// A1
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/vector.hpp>
int main()
{
        std::vector<char> vec(25, 'A');
        std::ofstream fout("A.txt");
        boost::archive::text_oarchive(fout) & vec;
        return 0;
}
----------------------------------
// A2
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/vector.hpp>
template<typename Archive>
struct X
{
        template<typename T> 
        void operator<<(const T &t)
        { 
                Archive &archive = (*(Archive *) NULL);
                archive << t; 
        }
        template<typename T> 
        void operator>>(T &t)
        { 
                Archive &archive = (*(Archive *) NULL);
                archive >> t; 
        }
};
// This function is instantiated by the compiler, but never executed.
void dummy()
{
        typedef boost::archive::text_iarchive IArchive;
        typedef boost::archive::text_oarchive OArchive;
        std::vector<char> *pt = NULL;
        X<OArchive> & oar = * (X<OArchive> *) NULL;
        oar << pt;
                
        X<IArchive> & iar = * (X<IArchive> *) NULL;
        iar >> pt;
}
int main()
{
        std::vector<char> vec(25, 'A');
        std::ofstream fout("A.txt");
        boost::archive::text_oarchive(fout) & vec;
        return 0;
}
----------------------------------
// B
#include <fstream>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/serialization/vector.hpp>
int main()
{
        std::vector<char> vec;
        std::ifstream fin("A.txt");
        
        // If A1 produced the archive, this line succeeds.
        // If A2 produced the archive, this line will silently fail.
        boost::archive::text_iarchive(fin) & vec; 
        
        return 0;
}
----------------------------------