I'm toying with ZeroMQ and Cereal to pass data structures (mostly std::vector
of numeric types) between different processes. I've managed to successfully achieve what I wanted, but I'm getting a Segmentation Fault at the end of execution, and after further inspection with valgrind
I've noticed that memory is being leaked/not freed.
server.cpp
(receiving side):
#include <zmq.hpp>
#include <string>
#include <unistd.h>
#include <sstream>
#include <cereal/archives/binary.hpp> // serializer
#include <cereal/types/vector.hpp> // to allow vector serialization
///////////////////////
int receiveMSG(zmq::socket_t& _ss, std::string& _dd){
_dd.clear(); // empty string
zmq::message_t msg;
int n = _ss.recv(&msg);
char * tmp;
memcpy(tmp,msg.data(),msg.size());
_dd = std::string (tmp,msg.size());
return n;
};
///////////////////////
template <typename _t>
void vectorDeserializer(std::vector<_t>& _output, std::string& _serializedVector){
std::stringstream ss;
ss << _serializedVector;
cereal::BinaryInputArchive iarchive(ss);
iarchive(_output);
ss.clear();
};
/////////////////////////////////////////////////////
int main () {
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_REP);
socket.bind ("tcp://*:4455");
std::string ts = "dummy";
std::vector<float> vec (10,5.5);
receiveMSG(socket,ts);
vectorDeserializer(vec,ts);
for (int i = 0; i < vec.size(); ++i) printf("%f\t",vec[i]);
printf("\n");
return 0;
}
client.cpp
(sending side):
#include <zmq.hpp>
#include <string>
#include <vector>
#include <cereal/archives/binary.hpp> // serializer
#include <cereal/types/vector.hpp> // to allow vector serialization
#include <sstream>
///////////////////////
int sendMSG(zmq::socket_t& _ss, std::string& _dd){
zmq::message_t msg (_dd.size());
return _ss.send(msg);
};
///////////////////////
template <typename _t>
void vectorSerializer(std::vector<_t>& _input, std::string& _serializedVector){
std::stringstream ss; // any stream can be used
cereal::BinaryOutputArchive oarchive(ss); // Create an output archive
oarchive(_input);
_serializedVector = ss.str();
};
///////////////////////
int main () {
zmq::context_t context (1);
zmq::socket_t socket (context, ZMQ_REQ);
std::cout << "Connecting to server…" << std::endl;
socket.connect ("tcp://localhost:4455");
std::vector<float> tt (5,1.5);
std::string ssss="dummy";
vectorSerializer(tt,ssss);
sendMSG(socket,ssss);
return 0;
}
The output from valgrind
is on this Pastebin link. Apparently the destructor of zmq::socket_t
trhoughs a segfault due to an Invalid read of size 4
when closing the socket. Additionally, there is a lot of Conditional jump or move depends on uninitialised value(s)
reported by valgrind
when calling memcpy
.
What exactly am I missing in my code? Or is the issue on the libraries inner code?