문제

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?

도움이 되었습니까?

해결책

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.

다른 팁

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top