|
Boost Users : |
Subject: [Boost-users] boost serialisation: portable binary format cant cope with -1
From: Avi Bahra (avibahra_at_[hidden])
Date: 2010-03-09 12:33:16
I have a strange bug where on the AIX platform I get:
boost::archive exception for TimeStruct : integer cannot be represented
for boost version 1.40
on restoring a class(TimeStruct) that has a integer
data member of value of -1.
Its seems strange that the exception is
_only_ raised when restoring the class, and not saving
Its missing some symmetry somewhere ?
Here is the stack trace:
//boost::serialization::throw_exception<portable_binary_iarchive_exception>,
//portable_binary_iarchive::load_impl,
//portable_binary_iarchive::load<int>,
//boost::archive::load_access::load_primitive<portable_binary_iarchive,int>,
//boost::archive::detail::load_non_pointer_type<portable_binary_iarchive,int>::load_primitive::invoke,
//boost::archive::detail::load_non_pointer_type<portable_binary_iarchive,int>::invoke,
//boost::archive::load<portable_binary_iarchive,int>,
//boost::archive::detail::common_iarchive<portable_binary_iarchive>::load_override<int>,
//portable_binary_iarchive::load_override<int>,
//boost::archive::detail::interface_iarchive<portable_binary_iarchive>::operator
>><int>,
//boost::archive::detail::interface_iarchive<portable_binary_iarchive>::operator
&<int>,
//TimeStruct::serialize<portable_binary_iarchive>,
// .....
This is raised in:
void
portable_binary_iarchive::load_impl(boost::intmax_t & l, char maxsize){
char size;
l = 0;
this->primitive_base_t::load(size);
if(0 == size){
return;
}
bool negative = (size < 0);
if(negative)
size = -size;
if(size > maxsize)
boost::serialization::throw_exception(
portable_binary_iarchive_exception()
);
.....
The exception is raised because size=255 and maxsize=4 ?
Here is the example which produces the exception:
Please note that you will have to dig out and
compile the portable binary archives out of the
boost serialisation examples dirs.
//================ Main.cpp =========================
// This example demonstrates a possible bug in
// portable binary format on AIX when serialising -1
// that is specific only to the AIX compiler/platform
// (i.e HPUX/Acc and linux/gcc run without any problems)
// However on AIX on the restore I get:
// boost::archive exception for TimeStruct : integer cannot be
represented
//
// This test consists of 1 files
// 1/ Main.cpp
//
#include <sstream>
#include <ostream>
#include <iostream>
#include <fstream>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include "portable_binary_oarchive.hpp"
#include "portable_binary_iarchive.hpp"
#include <boost/serialization/serialization.hpp>
using namespace std;
class TimeStruct {
public:
TimeStruct() : hour_(-1), minute_(-1) {}
TimeStruct(int hour, int min) : hour_(hour), minute_(min) {}
bool operator==(const TimeStruct& rhs) const { return ((hour_ ==
rhs.hour_) && (minute_ == rhs.minute_));}
bool operator!=(const TimeStruct& rhs) const { return !operator==(rhs);}
int hour() const { return hour_;}
int minute() const { return minute_;}
bool isNULL() const { return (hour_ == -1) || (minute_ == -1); }
// returns struct in the format hh:mm
std::string toString() const {
std::stringstream ss;
if (hour_ == -1) ss << hour_;
else if (hour_ < 10) ss << "0" << hour_;
else ss << hour_;
ss << ":";
if (minute_ == -1) ss << minute_;
else if (minute_ < 10) ss << "0" << minute_;
else ss << minute_;
return ss.str();
}
private:
int hour_;
int minute_;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/) {
ar & hour_;
ar & minute_;
}
};
bool compare(const TimeStruct& lhs, const TimeStruct& rhs)
{
if (lhs.isNULL() && rhs.isNULL()) return true;
if (lhs.isNULL() && !rhs.isNULL()) return false;
if (!lhs.isNULL() && rhs.isNULL()) return false;
if (lhs.hour() != rhs.hour()) return false;
if (lhs.minute() != rhs.minute()) return false;
return true;
};
static void save(const std::string& fileName, const TimeStruct& ts, bool
textArchive);
static void restore(const std::string& fileName, TimeStruct& ts, bool
textArchive);
int main()
{
{
TimeStruct saved;
save("fred.txt",saved,true);
TimeStruct restored;
restore("fred.txt",restored,true);
assert(saved == restored);
}
{
TimeStruct saved;
save("fred.txt",saved,false);
TimeStruct restored;
restore("fred.txt",restored,false);
assert(saved == restored);
}
return 0;
}
void save(const std::string& fileName, const TimeStruct& ts, bool
textArchive)
{
if ( textArchive ) std::cout << "Text archive Saving " << ts.toString();
else std::cout << "portable binary archive Saving " <<
ts.toString();
try {
if (textArchive) {
std::ofstream ofs( "fred.txt" );
boost::archive::text_oarchive ar( ofs );
ar << ts;
}
else {
std::ofstream ofs( fileName.c_str(), ios::binary );
portable_binary_oarchive ar(ofs);
ar << ts;
}
std::cout << " OK \n";
}
catch (const boost::archive::archive_exception& ae) {
std::cout << " save " << fileName
<< " failed. boost::archive exception for TimeStruct "
<< ": " << ae.what() << std::endl;
}
}
void restore(const std::string& fileName, TimeStruct& restored, bool
textArchive)
{
if ( textArchive ) std::cout << "Text archive Restoring ";
else std::cout << "portable binary archive Restoring " ;
try {
if ( textArchive ) {
std::ifstream ifs( fileName.c_str() );
boost::archive::text_iarchive ar( ifs );
ar >> restored;
}
else {
std::ifstream ifs( fileName.c_str(), ios::binary );
portable_binary_iarchive ar( ifs );
ar >> restored;
}
std::cout << restored.toString() << " OK \n";
}
catch ( const boost::archive::archive_exception& ae ) {
std::cout << " restore " << fileName
<< " failed. boost::archive exception for TimeStruct "
<< ": " << ae.what() << std::endl;
}
}
Best regards,
Ta,
Avi
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