The text I write here is the following problem that I opened earlier in another thread in Boost: Serialization / De-serialization of a custom C ++ object passed through the ZeroMQ pull socket . Compilation problems in an earlier thread were resolved using a type of textarchive rather than binaryarchive, but now I am experiencing a run-time problem when de-serializing. I repeat here the earlier text with a new description of the problem for your convenience. I am relatively new to C ++ and appreciate any further help.
Description:
I have a C ++ class called GenericMessage that simply contains an identifier and data as its members (see code snippet 2 below - GenericMessage.hxx). My intention is to serialize an instance of this class and send it through the ZeroMQ socket, which implements the push pattern.
The serialization and sending task was implemented in the ZMQHandler class (see the sendToBE function), which is placed in the name of the ZMQHandler.hxx header file, shown in code snippet 3 below. This class is created by TestFE.cxx , shown in the 4th code fragment below.
Retrieving and de-serializing an instance of GenericMessage is implemented in TestBE.cxx , available in the fifth code snippet below. My intention is to get an instance of GenericMessage through a ZMQ socket (i.e. a Pull socket), de-serialize it, and then print its elements to standard output.
Problem:
When I start the receiver (i.e. TestBE.cxx), I checked here that I can transfer data from TestFE.cxx to TEstBE.cxx through the ZMQ socket. However, I got the exception indicated in the first code snippet below when I try to de-serialize the input archive on line 28 in TestBE.cxx (see the fifth code snippet very below, line 28 is marked).
-, -, TestBE.cxx 5? , ? , st , ZMQHandler.cxx( 3 - sendToBE). .
CODE SNIPPET 1 GDB OUTPUT backtrace
$ gdb TestBE
GNU gdb (GDB) 7.5-ubuntu
.....
(gdb) r
Starting program: /TestBE
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/i386-linux-gnu/libthread_db.so.1".
[New Thread 0xb7c12b40 (LWP 16644)]
[New Thread 0xb7411b40 (LWP 16645)]
Connecting to FE...
!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!
**CHAR [22 serialization::archive 9 0 1 0
0 1 12 Hello there!]
terminate called after throwing an instance of 'std::logic_error'
what(): basic_string::_S_construct null not valid**
!!!!!!!!!!!!!!!!!!!! !!!!!!!!!!!!!!!!!!!!!!!!!!!
Program received signal SIGABRT, Aborted.
0xb7fdd424 in __kernel_vsyscall ()
(gdb) bt
x=@0x805cb40: 0x805cb50, file_version=0) at /usr/include/boost/archive/detail/iserializer.hpp:327
at /usr/include/boost/archive/detail/iserializer.hpp:524
at /usr/include/boost/archive/detail/iserializer.hpp:592
at /usr/include/boost/archive/detail/common_iarchive.hpp:66
at /usr/include/boost/archive/basic_text_iarchive.hpp:65
at /usr/include/boost/archive/text_iarchive.hpp:82
at /usr/include/boost/archive/detail/interface_iarchive.hpp:60
CODE SNIPPET 2 (GenericMessage.hxx)
#include <iostream>
#include <string>
#include <sstream>
#include <boost/serialization/serialization.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
template <class T>
class GenericMessage {
public:
GenericMessage():
beId(-1),
data(NULL)
{}
GenericMessage(int id, T msg):
beId(id),
data(msg)
{}
~GenericMessage(){}
T getData()
{
return data;
}
std::string toString()
{
std::ostringstream ss;
ss << getBeId();
std::string ret = ss.str();
return ret;
}
void setBeId(int id)
{
beId = id;
}
int getBeId()
{
return beId;
}
private:
friend class boost::serialization::access;
int beId;
T data;
template <class Archive>
void serialize(Archive & ar, const unsigned int version)
{
ar & beId;
ar & data;
}
};
CODE SNIPPET 3 (ZmqHandler.hxx)
#include "zmq.hpp"
#include "GenericMessage.hxx"
#include <unistd.h>
#include <cassert>
template <class A>
class ZmqHandler {
public:
ZmqHandler():
mContext(1),
mOutbHandlerSocket(mContext, ZMQ_PUSH)
{
mOutbHandlerSocket.bind ("tcp://*:5555");
}
~ZmqHandler() {}
void sendToBE(GenericMessage<A> *theMsg)
{
std::ostringstream archive_stream;
boost::archive::text_oarchive archive(archive_stream);
try
{
archive << theMsg;
} catch (boost::archive::archive_exception& ex) {
std::cout << "Archive Exception during deserializing:" << std::endl;
std::cout << ex.what() << std::endl;
} catch (int e) {
std::cout << "EXCEPTION " << e << std::endl;
}
std::string outbound_data_ = archive_stream.str();
const char * buf = outbound_data_.c_str();
int len = strlen((const char*)buf);
std::cout << "LENGTH [" << len << "]" << std::endl;
zmq::message_t msgToSend(len);
memcpy ((char *) msgToSend.data(), buf, len);
if(memcmp((char *) msgToSend.data(), buf, len) != 0)
{
std::cout << "memcpy error!" << std::endl;
}
mOutbHandlerSocket.send(msgToSend);
std::cout << "SENT request: [" << theMsg->toString() << "]" << std::endl;
}
private:
zmq::context_t mContext;
zmq::socket_t mOutbHandlerSocket;
};
CODE SNIPPET 4 (TestFE.cxx)
#include "ZmqHandler.hxx"
int main ()
{
ZmqHandler<std::string> zmqHandler;
int counter = 1;
while(1)
{
std::string data = "Hello there!\0";
GenericMessage<std::string> msg(counter, data);
zmqHandler.sendToBE(&msg);
counter++;
sleep(1);
}
return 0;
}
CODE SNIPPET 5 (TestBE.cxx)
#include "zmq.hpp"
#include "GenericMessage.hxx"
#include <fstream>
int main ()
{
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_PULL);
std::cout << "Connecting to FE..." << std::endl;
socket.connect ("tcp://localhost:5555");
while(1){
zmq::message_t reply;
socket.recv (&reply);
const char *buf = static_cast<const char*>(reply.data());
std::cout << "CHAR [" << buf << "]" << std::endl;
std::string input_data_(buf);
std::istringstream archive_stream(input_data_);
boost::archive::text_iarchive archive(archive_stream);
GenericMessage<std::string> *theMsg;
try
{
archive >> theMsg;
} catch (boost::archive::archive_exception& ex) {
std::cout << "Archive Exception during deserializing:" << std::endl;
std::cout << ex.what() << std::endl;
} catch (int e) {
std::cout << "EXCEPTION " << e << std::endl;
}
std::cout << "ID" << theMsg->getBeId() << std::endl;
std::cout << "Data" << theMsg->getData() << std::endl;
}
return 0;
}