如果设置protobuf可序列化类的值,为什么会出现zmq错误?

时间:2018-06-25 13:41:02

标签: c++11 protocol-buffers zeromq

我正在测试使用zmq作为套接字和网络工具以及protobuf进行序列化的代码。

代码收到一个zmq_message并将其解析为protobuf类,作为回报,我更改了一个类成员的值,并将同一类发送回请求者。

在此过程中,以某种方式zmq断言check()失败。我真的不知道为什么会这样,因为一切对我来说都很好。

代码在主文件中看起来像这样:

zmq::socket_t external(context, ZMQ_REP);
external.bind("tcp://*:29067");

zmq::message_t request;
external.recv(&request);
msg.deserialize(request);

msg.set_probed_value(12.0);
zmq::message_t response = msg.serialize();
external.send(response);

反序列化方法看起来像这样。

_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));

和序列化方法如下:

zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;

set_probed_value() 如下:

void set_probed_value(const double& val)
{
    _msg.clear_probed();
    _msg.set_probed(val);
}

我知道一个事实,就是当我将probed的值设置为与解析时设置的值不同的数字时,会引起问题。如果我删除该行msg.set_probed_value(12.0),则不会发生任何异常,并且一切正常。

  

断言失败:检查()(/apps/zmq/libzmq/src/msg.cpp:347)

2 个答案:

答案 0 :(得分:1)

可疑?违反ZeroMQ API发布的原则

众所周知,所有消息处理都相当脆弱。

首先要进行显式的内容复制,而不是直接处理含糖的reinterpret_cast<...>( msg.data() )内容(由ZeroMQ传递的指针引用)的直接语法怎么办?

  

使用zmq_msg_copy()复制邮件后,避免修改邮件内容 这样做会导致不确定的行为 >。如果您需要的是实际的硬拷贝,请使用zmq_msg_init_size()分配新消息,并使用memcpy()复制消息内容。

根据已发布的ZeroMQ API强烈建议,在完成安全内容复制之后,也建议使用close()消息对象的显式request。 >

  

从不直接访问zmq_msg_t成员,而始终使用zmq_msg函数家族。

ZeroMQ API明确警告不要尝试以任何其他方式来操纵消息内容,而不是使用API​​发布的函数/方法。即使花费更多的代码和更多的SLOC-s,也最好避免使用任何此类技巧。

答案 1 :(得分:0)

您确定该zmq消息msg中的NULL终止吗?

_msg.ParseFromString(reinterpret_cast<const char*>(msg.data()));

否则,这将使您的_msg充满垃圾,因为它读到了您认为是字符串的结尾。

我问的原因是:

创建/发送邮件时,您不要包含NULL

zmq::message_t request(_msg.ByteSize());
std::string value = _msg.SerializeAsString();
memcpy(request.data(), reinterpret_cast<const void*>(value.c_str()), value.size());
return request;