Frage

I have a problem sending zmq message built from the pointer to struct, which contains other struct.

The server code:

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

using namespace zmq;
using namespace std;

struct structB{
    int a;
    string c;
};

struct structC{
    int z;
    struct structB b;
};

int main()
{
    context_t context(1);
    socket_t *socket = new socket_t(context,ZMQ_REP);
    socket->bind("tcp://*:5555");

    message_t *request = new message_t();   
    socket->recv(request);

    struct structB messageB; 
    messageB.a=0;
    messageB.c="aa";

    struct structC *messageC = new struct structC;
    messageC->z = 4;
    messageC->b = messageB;

    char *buffer = (char*)(messageC);
    message_t *reply = new message_t((void*)buffer,
                       +sizeof(struct structB)
                       +sizeof(struct structC)
                       ,0);
    socket->send(*reply);

    return 0;
}

Client code:

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

using namespace std;
using namespace zmq;

struct structB{
    int a;
    string c;
};

struct structC{
    int z;
    struct structB b;
};

int main()
{ 
    context_t context(1);
    socket_t *socket = new socket_t(context,ZMQ_REQ);
    socket->connect("tcp://*:5555");

    const char* buffer = "abc";
    message_t *request = new message_t((void*)buffer,sizeof(char*),0);
    socket->send(*request);

    message_t *reply = new message_t;
    socket->recv(reply);

    struct structC *messageC = new struct structC;
    messageC = static_cast<struct structC*>(reply->data());

cout<<messageC->b.a<<endl;//no crash here

    struct structB messageB = messageC->b;//Segmentation fault (core dumped)

    return 0;
}

This program crashes when I try to use string called "c" from structB. It doesn't matter if I try to print it, or assign whole structB as in above example.

Where is the problem? Should I create message_t *reply on server side in different way?

War es hilfreich?

Lösung

You cannot send string over network as std::string is a container. You can use flexible array member or big size array or write a small class which is serializable (you have to write code by yourself to prepare buffer) to send the data.

When you do struct structB messageB = messageC->b;, pointer members of std::string member embed inside messageC->b might be dereference in copy constructor or std::string which is possibly causing the segmentation fault.

Example of large char array would be:

struct structB{
    int a;
    char c[MAX_LENGTH];
};

Later

struct structB messageB; 
messageB.a=0;
strcpy(messageB.c,"aa"); // #include<cstring> or use std::copy from <algorithm>

struct structC *messageC = new struct structC;
// I guess you want this(not sure) messageC->z = static_cast<int>( sizeof(int) + strlen(messageB) + 1 );
messageC->z = 4;
messageC->b = messageB;

And then

const int length = sizeof(int) /* z */ + sizeof(int) /* a */ + strlen("aa") + 1;
zmq::message_t msg (length);
memcpy (msg.data (), &messageC, length);
socket->send(msg);

These are some changes required at server side, you need to make similar changes at client side also.

As a side note, your code is very messy, don't deploy it in larger applications before sorting out few things like removal of unnecessary new and properly representing nested structures.

Andere Tipps

Your structures are not POD. Class "string" can't be copied as memory heap. There is a problem.

Use c.c_str() and c.size() to copy in as memory block.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top