【问题标题】:Can zmq::message_t's be reused after being sent?zmq::message_t 发送后可以重复使用吗?
【发布时间】:2019-10-29 20:20:53
【问题描述】:

我正在使用 ZeroMQ 来实现一个玩具通信协议;这是我第一次使用这个框架/库。

现在,在我的协议中,多条连续消息由某一方发送,所有消息都具有相同的大小。所以 - 我想,我会避免重新分配它们,而只是尝试用不同的内容重新填充消息数据缓冲区,例如:

zmq::message_t msg { fixed_common_size };
while (some_condition()) {
    my_filling_routine(msg.data(), fixed_common_size);
    the_socket.send(msg);
}

但是在这个循环的第二次迭代中,我得到了一个分段错误; msg.data() 不是 nullptr。我突然想到,ZeroMQ 可能会以某种方式蚕食内存,因此我需要编写如下内容:

zmq::message_t msg { fixed_common_size };
char buffer[fixed_common_size];
while (some_condition()) {
    my_filling_routine(buffer, fixed_common_size);
    msg.rebuild(buffer, fixed_common_size);
    the_socket.send(msg);
}

但我确信这会导致取消分配和重新分配。

那么,rebuild() 真的是必要的吗,还是只是我的代码中的一些错误?

注意:我使用的是 Unix 套接字,以防答案取决于此。

【问题讨论】:

    标签: segmentation-fault ipc zeromq


    【解决方案1】:

    不,您不能在发送 zmq::message_t 后重复使用它。

    首先,欢迎来到 ZeroMQ,这是 从业者的好去处。

    ZeroMQ API 非常明确地警告这些问题。成功调用 zmq_msg_send(),引用消息有效负载,并不意味着消息本身已实际发送。

    您最好尝试想象调用只是将责任“移动”从您的应用程序代码到 ZeroMQ 引擎(在工厂内部,在 Context() 中实例化了一个 IO 线程池-实例...)。

    在调用过程中,传递给 zmq_msg_send()zmq_msg_t 结构无效

    以及下一个更好的永远不要在以后的任何时候触摸它,如上文所述:o)

    分配器的最大“生态”绕过是重新使用整个-消息,如:

    如果您想将相同的消息发送到多个套接字,您必须使用复制它(例如使用 zmq_msg_copy())。


    复制时的额外警告...

    再提一点:可以复制,但以后敢尝试修改……

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

    永远不要直接访问zmq_msg_t 成员,而是始终使用zmq_msg-family 函数。

    【讨论】:

    • 好的,但这意味着您基本上需要为每条消息分配堆(或者您预先分配并提前您的指针)。对吗?
    • 关于您的最终评论: 1. 使用zmq::message_t 对象总是安全的吗?还是直接访问zmq_msg_t 成员一样危险? 2. 我应该避免 memcpy()'ing 到my_msg.data() 吗?
    • 最好将所有邮件视为脆弱的身体,而不是可重复使用或 DIY-s。有一些规则,零拷贝可能对一个人的代码有益,但总的来说,要小心记录为安全的内容,并将其余所有内容视为不推荐的做法。在旧版本中可能已经容忍了低级技巧,所以要相当谨慎。最好的下一步似乎是查看 API 版本 4.2,并检查在重新包装本机 ZeroMQ 版本及其首选版本时使用了哪些 API。已弃用的策略。
    猜你喜欢
    • 2022-09-22
    • 2014-12-16
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-04
    • 1970-01-01
    相关资源
    最近更新 更多