Boost:反序列化通过 ZeroMQ 拉套接字传递的自定义 C++ 对象

2023-12-02

我在这里写的文字是我之前在另一个线程中打开的后续问题Boost:序列化/反序列化通过 ZeroMQ 拉套接字传递的自定义 C++ 对象。早期线程中的编译问题已通过使用文本存档类型而不是二进制存档解决,但现在我在反序列化时遇到运行时问题。为了您的方便,我在这里用新的问题陈述重复之前的文本。我对 C++ 领域比较陌生,感谢任何进一步的帮助。

描述:

我有一个名为的 C++ 类通用消息它仅保存一个 id 和数据作为其成员(请参阅下面的代码片段 2 - GenericMessage.hxx)。我的目的是序列化此类的实例并通过实现推送模式的 ZeroMQ 套接字发送它。

序列化和发送任务已实现类 ZMQHandler(参见sendToBE函数)它被放置在一个名为ZMQHandler.hxx的头文件中,如图所示代码片段3以下。该类的实例化为测试FE.cxx显示在第四个代码片段 below.

GenericMessage实例的接收和反序列化实现在测试BE.cxx可用在第 5 个代码片段以下。我的目的是通过 ZMQ 套接字(即拉套接字)接收 GenericMessage 实例,对其进行反序列化,然后将其成员打印到标准输出。

问题陈述:

当我运行接收器(即 TestBE.cxx)时,我在这里验证了我可以通过 ZMQ 套接字将数据从 TestFE.cxx 传输到 TEstBE.cxx。但是,当我尝试对 TestBE.cxx 中第 28 行的输入存档进行反序列化时,我得到了下面第一个代码片段中显示的异常(请参阅下面的第五个代码片段,第 28 行已被标记)。

在代码片段 5 的 TestBE.cxx 中实现的反序列化过程中是否缺少某些内容?你认为我为什么会得到这个例外?难道我在 ZMQHandler.cxx 中实现的序列化过程中缺少 st (代码片段 3 - 函数 sendToBE)。提前致谢。

代码片段 1 GDB 输出和回溯

$ 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

代码片段 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;
  }

 };

代码片段 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;         
 };

代码片段 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;
 }

代码片段 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;
   }

你宣布theMsg作为指针(GenericMessage<std::string> *theMsg;).

尝试将该行更改为GenericMessage<std::string> theMsg;.`

异常的真正来源

In the GenericMessage默认构造函数,你初始化data with NULL。但是,您不允许初始化std::string with a 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 );
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Boost:反序列化通过 ZeroMQ 拉套接字传递的自定义 C++ 对象 的相关文章

随机推荐

  • 我应该使用 HTML::Parser 还是 XML::Parser 来提取和替换文本? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我希望能够提取所有纯文本并从 HTML XHTML 文档中分析 修改 然后根据需要进行替换 我可以使用以下方法来做到这一点吗HTML 解析器或者应该是XML 解析器 有没有人知道有什
  • 解释 Ruby on Rails 中的迭代器语法

    我开始学习 Ruby on Rails 发现自己对语法感到困惑 所以我必须阅读一些 Ruby 语法 我从中学到了语法http www cs auckland ac nz references ruby doc bundle Manual m
  • PyQt QThread 多线程不起作用

    I have 2 QListWidget lists List2 is being filled when some item has been selected from List1 问题是 在填充 List2 之前 我必须执行很多任务
  • 清除页面中的所有单选按钮

    我的应用程序中有很多动态生成的单选按钮Windows 窗体项目 可以根据数据库中的值来检查它们 我想通过单击按钮清除所有单选按钮 我怎样才能做到这一点 检查一下 private void button1 Click object sende
  • Visual Studio“任何 CPU”目标是什么意思?

    我对 Visual Studio 2008 中的 NET 平台构建选项有一些困惑 什么是 Any CPU 编译目标 它会生成什么类型 的文件 我检查了这个 任何 CPU 构建的输出可执行文件 发现它们是 x86 可执行文件 谁不会看到这一点
  • 通过需要考虑多种成本的矩阵的最佳路径

    例如给出以下矩阵 0 8 0 3 0 8 8 0 3 0 0 5 0 1 0 6 0 0 对于每个元组 第一个数字是食物 第二个数字是水 我需要从右下角到左上角 并且只能向上或向左移动 我需要收集尽可能多的食物和水 这样我才能活得尽可能长
  • XML 元素不会触发 TextBox ConvertBack 事件

    ValueFormattingConverter Convert被称为XmlElement ConvertBack从未被调用过 为什么 是否有义务将具有约束力的指令向下传递 文本框的使用是否会覆盖其自身的绑定设置 可以做什么 我的文本框
  • System.gc()什么时候做某事?

    我知道Java中垃圾收集是自动的 但我明白如果你打电话System gc 在您的代码中 JVM 可能会也可能不会决定在此时执行垃圾收集 这具体是如何运作的 当 JVM 看到时 它到底根据什么基础 参数决定执行 或不执行 GCSystem g
  • Python Instagram 使用请求登录

    我正在尝试使用 python 登录 Instagram 我能够获得 csrf 令牌 但是requests Session post 似乎没有正确地将登录数据发布到网站 我总是得到class no js not logged in clien
  • 如何获取错误输出并将其存储在变量或文件中

    我在弄清楚如何获取错误输出并将其存储在 ksh 的变量或文件中时遇到了一些麻烦 所以在我的脚本中我有cp p source file destination里面一个while loop 当我收到以下错误时 cp source file Th
  • 使用 : 在列表或 numpy 数组中进行多重切片

    我在尝试弄清楚如何提取列表中间隔一些索引的多个值时遇到一些困难 例如 给定一个列表l 0 1 2 3 4 5 6 7 8 9 10 我只想提取值 1 2 3 and 6 7 8 9 我可以l 1 4 l 6 1 但是有没有办法这样写l 1
  • 使用 Jersey 进行多线程处理

    这是两个似乎相互矛盾的链接 我宁愿相信文档 Link 1 服务器上的请求处理默认以同步处理模式进行 Link 2 它已经是多线程的了 我的问题 哪个是对的 它可以同时是同步和多线程吗 为什么文档这么说 如果已知资源方法执行需要很长时间才能计
  • [__NSCFDictionary objectAtIndex:]:发送到实例的无法识别的选择器

    我正在尝试将 Json 文件解析到表视图中 但收到此错误 NSCFDictionary objectAtIndex 发送到实例的无法识别的选择器 并且应用程序正在崩溃 请帮助我 我是 iOS 开发新手 My Code implementat
  • 为什么MKMapView中的clusterAnnotationForMemberAnnotations没有被调用?

    我有一个简单的地图视图 IBOutlet private var mapView MKMapView 然后我一一添加注释 mapView addAnnotation Annotation user user 并向他们展示全部 mapView
  • 如何获取GPU信息?

    我有一个任务是用 C 收集有关 Windows 中 GPU 的信息 但我不知道从哪里开始 任何想法 更新 我想要名称 vram dac 制造商 版本 时钟 update2 如果我使用 win32 videocontroller 类 我只是获
  • 如何在 Python 中多次训练 sklearn 中的 SVM 分类器?

    我想知道是否可以在 for 循环中多次从 Python 中的 sklearn 训练 SVM 分类器 我的想法如下 for i in range 0 10 data np load somedata labels np load somela
  • android webview 导致空指针

    我的布局中有这个
  • Qt 创建者错误

    启动项目调试 然后 Running build steps for project Text Editor Starting c qt 2010 05 qt bin qmake exe C Qt 2010 05 Text Editor Te
  • iOS 8.3 中的 UIDatePicker 内存泄漏

    当在运行 IOS 8 3 的 iPad 上的弹出窗口中使用 UIDatePicker 时 我发现内存泄漏 每次弹出日期选择器然后关闭时 我都会在多次内存泄漏中得到大约 5K 的信息 泄漏的对象是 NSDateComponents 负责的框架
  • Boost:反序列化通过 ZeroMQ 拉套接字传递的自定义 C++ 对象

    我在这里写的文字是我之前在另一个线程中打开的后续问题Boost 序列化 反序列化通过 ZeroMQ 拉套接字传递的自定义 C 对象 早期线程中的编译问题已通过使用文本存档类型而不是二进制存档解决 但现在我在反序列化时遇到运行时问题 为了您的