Boost: De-serialization of a custom C ++ object passed through a ZeroMQ pull socket

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
 #0  0xb7fdd424 in __kernel_vsyscall ()
 #1  0xb7c7a1df in raise () from /lib/i386-linux-gnu/libc.so.6
 #2  0xb7c7d825 in abort () from /lib/i386-linux-gnu/libc.so.6
 #3  0xb7e608ad in __gnu_cxx::__verbose_terminate_handler() () from /usr/lib/i386-  linux-gnu/libstdc++.so.6
 #4  0xb7e5e4f3 in ?? () from /usr/lib/i386-linux-gnu/libstdc++.so.6
 #5  0xb7e5e52f in std::terminate() () from /usr/lib/i386-linux-gnu/libstdc++.so.6
 #6  0xb7e5e825 in __cxa_rethrow () from /usr/lib/i386-linux-gnu/libstdc++.so.6
 #7  0x0804c1d4 in    boost::archive::detail::pointer_iserializer<boost::archive::text_iarchive,    GenericMessage<std::string> >::load_object_ptr (this=0x8054444, ar=..., 
 x=@0x805cb40: 0x805cb50, file_version=0) at    /usr/include/boost/archive/detail/iserializer.hpp:327
 #8  0xb7f3839d in boost::archive::detail::basic_iarchive::load_pointer(void*&,  boost::archive::detail::basic_pointer_iserializer const*,  boost::archive::detail::basic_pointer_iserializer const* (*) (boost::serialization::extended_type_info const&)) () from  /usr/lib/libboost_serialization.so.1.49.0
 #9  0x0804bea9 in    boost::archive::detail::load_pointer_type<boost::archive::text_iarchive>::invoke<GenericMes     sage<std::string>*> (ar=..., t=@0xbfffef70: 0xbfffeff8)
 at /usr/include/boost/archive/detail/iserializer.hpp:524
 #10 0x0804be55 in boost::archive::load<boost::archive::text_iarchive,                                  GenericMessage<std::string>*> (ar=..., t=@0xbfffef70: 0xbfffeff8)
 at /usr/include/boost/archive/detail/iserializer.hpp:592
 #11 0x0804be36 in   boost::archive::detail::common_iarchive<boost::archive::text_iarchive>::load_override<Gener icMessage<std::string>*> (this=0xbfffef84, t=@0xbfffef70: 0xbfffeff8)
  at /usr/include/boost/archive/detail/common_iarchive.hpp:66
 #12 0x0804be14 in  boost::archive::basic_text_iarchive<boost::archive::text_iarchive>::load_override<GenericMe ssage<std::string>*> (this=0xbfffef84, t=@0xbfffef70: 0xbfffeff8)
  at /usr/include/boost/archive/basic_text_iarchive.hpp:65
 #13 0x0804bdf2 in boost::archive::text_iarchive_impl<boost::archive::text_iarchive>::load_override<GenericMes sage<std::string>*> (this=0xbfffef84, t=@0xbfffef70: 0xbfffeff8)
  at /usr/include/boost/archive/text_iarchive.hpp:82
 #14 0x0804bcec in      boost::archive::detail::interface_iarchive<boost::archive::text_iarchive>::operator>> <GenericMessage<std::string>*> (this=0xbfffef84, t=@0xbfffef70: 0xbfffeff8)
 at /usr/include/boost/archive/detail/interface_iarchive.hpp:60
 #15 0x0804b2a1 in main () at TestBE.cxx:28

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 ()
 {
    //  Prepare our context and socket
    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
       {
       /* !!!!!!!!!! LINE 28 is the following !!!!!!!!!!*/
         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;
   }
+1
1

theMsg (GenericMessage<std::string> *theMsg;).

GenericMessage<std::string> theMsg;.

GenericMessage data NULL. std::string NULL. data .

GenericMessage()
: beId(-1) 
{}

T , .

() # 1

zmq::message_t () NULL. , , , .

// snip
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);  // assumes a null-term string
std::string input_data_( buf, reply.size() ); 
// snip

() # 2

, - ZmqHandler.hxx.

// snip
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;
}
// snip

memcpy ( ). - :

std::string outbound_data_ = archive_stream.str();
// no need to use the c-style string function 'strlen'
int len = outbound_data_.length();
std::cout << "LENGTH [" << len << "]" << std::endl;

zmq::message_t msgToSend(len);
memcpy( msgToSend.data(), outbound_data_.data(), len );
0

All Articles