zeromq / cppzmq

Header-only C++ binding for libzmq
http://www.zeromq.org
MIT License
1.95k stars 757 forks source link

message_t::to_string inserts a trailing null char and breaks string comparisons #396

Open dpellegr opened 4 years ago

dpellegr commented 4 years ago

Text messages sent via zmq get a trailing null char on the receiver side. The method message_t::to_string[_view] return a string size which is one byte larger than expected. Comparison between such returned strings are broken unless one manually constructs a longer string and then sets the last char to null.

// req.cpp

#include <string>
#include <iostream>
#include <zmq.hpp>

int main() {
  zmq::context_t ctx;
  zmq::socket_t sock(ctx, zmq::socket_type::req);
  sock.connect("ipc:///tmp/zmqsocket");
  zmq::message_t msg{"abc"};
  sock.send(msg);
  sock.recv(msg);
  std::cout << msg.to_string_view() << std::endl;
  return 0;
}
// rep.cpp

#include <string>
#include <iostream>
#include <zmq.hpp>

int main() {
  zmq::context_t ctx;
  zmq::socket_t sock(ctx, zmq::socket_type::rep);
  sock.bind("ipc:///tmp/zmqsocket");
  zmq::message_t msg;
  while (true) {
    std::cout << "listening..." << std::endl;
    sock.recv(msg);
    // msg.to_string_view() returns "abc\0", therefore msg.to_string_view() != "abc"
    // note that the trailing null char eludes printing functions

    // When constructing strings C++ optimizes away trailing null chars
    // One needs to build a longer string and set the last char to null later
    std::string s{"abcX"}; 
    s[3] = '\0';

    // now the comparison works
    if ( msg.to_string_view() == s) {
      sock.send(zmq::buffer("def"));
    } else {
      sock.send(zmq::buffer("???"));
    }
  }
  return 0;
}