Domanda

I'm having some issue serializing a std::string with boost::serialization on a text_oarchive. AFAICT, I have two identical pieces of code that behaves differently in two different programs.

This is the program that I believe is behaving correctly:

#include <iostream>
#include <string>
#include <sstream>

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>

template <typename T>
void serialize_deserialize(const T & src, T & dst)
{
    std::string serialized_data_str;

    std::cout << "original data: " << src << std::endl;

    std::ostringstream archive_ostream;
    boost::archive::text_oarchive oarchive(archive_ostream);
    oarchive << src;
    serialized_data_str = archive_ostream.str();
    std::cout << "serialized data: " << serialized_data_str << std::endl;

    std::istringstream archive_istream(serialized_data_str);
    boost::archive::text_iarchive iarchive(archive_istream);
    iarchive >> dst;
}


int main() 
{
    std::string archived_data_str = "abcd";
    std::string restored_data_str;

    serialize_deserialize<std::string>(archived_data_str, restored_data_str);

    std::cout << "restored data: " << restored_data_str << std::endl;

    return 0;
}

And this is its output:

original data: abcd
serialized data: 22 serialization::archive 10 4 abcd
restored data: abcd

(You can compile it with: g++ boost-serialization-string.cpp -o boost-serialization-string -lboost_serialization)

This one, on the other hand, is an excerpt of the program I'm writing (derived from boost_asio/example/serialization/connection.hpp) that serializes std::string data converting each character in its hex representation:

/// Asynchronously write a data structure to the socket.
template <typename T, typename Handler>
void async_write(const T& t, Handler handler)
{
  // Serialize the data first so we know how large it is.
  std::cout << "original data: " << t << std::endl;
  std::ostringstream archive_stream;
  boost::archive::text_oarchive archive(archive_stream);
  archive << t;
  outbound_data_ = archive_stream.str();
  std::cout << "serialized data: " << outbound_data_ << std::endl;
  [...]

And this is an excerpt of its output:

original data: abcd
serialized data: 22 serialization::archive 10 5 97 98 99 100 0

The version (10) is the same, right? So that should be the proof that I'm using the same serialization library in both programs.

However, I really can't figure out what's going on here. I've been trying to solve this puzzle for almost an entire work day now, and I'm out of ideas.

For anyone that may want to reproduce this result, it should be sufficient to download the Boost serialization example, add the following line

connection_.async_write("abcd", boost::bind(&client::handle_write, this, boost::asio::placeholders::error));

at line 50 of client.cpp, add the following member function in client.cpp

/// Handle completion of a write operation.
void handle_write(const boost::system::error_code& e)
{
  // Nothing to do. The socket will be closed automatically when the last
  // reference to the connection object goes away.
}

add this cout:

std::cout << "serialized data: " << outbound_data_ << std::endl;

at connection.hpp:59

and compile with:

g++ -O0 -g3 client.cpp -o client -lboost_serialization -lboost_system
g++ -O0 -g3 server.cpp -o server -lboost_serialization -lboost_system

I'm using g++ 4.8.1 under Ubuntu 13.04 64bit with Boost 1.53

Any help would be greatly appreciated.

P.s. I'm posting this because the deserialization of the std::strings isn't working at all! :)

È stato utile?

Soluzione

I see two causes of such behavior.

  1. The compiler does not explicitly converts "abcd" from const char * to std::string and the serialization handles it as a vector of "bytes" and not as an ASCII string. Changing the code to the connection_.async_write(std::string("abcd"), boost::bind(&client::handle_write, this, boost::asio::placeholders::error)); should fix the problem.
  2. Probably, the string type passed as the t argument of the async_write template method is not std::string but std::wstring and it is serialized not as an ASCII string ("abcd") but as an unsigned short vector and 97 98 99 100 is a decimal representation of the ASCII characters a, b, c and d.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top