Reading Flatbuffers objects sent via ZMQ in C++ throws unhandled exception

痴心易碎 提交于 2019-12-05 06:45:50

问题


I am trying to send a reasonably big Flatbuffers object over the network via ZMQ and then read it using C++. When accessing the object, I get unhandled exceptions that I don't know how to solve. Even this minimal example fails:

The flatbuffers schema:

namespace flatbuffer;
table TestBuf {
  testStatus:bool;
  testNumber:double;
  testInt:int;
}
root_type TestBuf;

The main.cpp using the REP socket:

int main() {
    zmq::context_t context(1);
    zmq::socket_t socket(context, ZMQ_REP);
    socket.bind("tcp://*:5555");

    std::cout << "Listening for requests." << std::endl;
    std::cout << "-----" << std::endl;

    double count = 0;
    while (1) {
        zmq::message_t request;
        socket.recv(&request);

        // Read incoming data
        auto reqmsg = flatbuffer::GetTestBuf(&request);
        std::cout << "Received: " << reqmsg << std::endl;

        flatbuffers::FlatBufferBuilder fbb;
        flatbuffer::TestBufBuilder builder(fbb);

        count++;
        builder.add_testNumber(count);      
        std::cout << "Sending " << count << std::endl;

        auto response = builder.Finish();
        fbb.Finish(response);

        // Send the flatbuffer
        int buffersize = fbb.GetSize();
        zmq::message_t message(buffersize);
        memcpy((void *)message.data(), fbb.GetBufferPointer(), buffersize);
        socket.send(message);
    }
    return 0;
}

The main.cpp using the REQ socket:

int main() {
    // Prepare ZMQ context and socket
    zmq::context_t context(1);
    zmq::socket_t socket(context, ZMQ_REQ);
    std::cout << "Sending out data requests." << std::endl;
    socket.connect("tcp://localhost:5555");

    double count = 0;
    while (1) {
        // Formulate response
        flatbuffers::FlatBufferBuilder fbb;
        flatbuffer::TestBufBuilder builder(fbb);

        count++;
        builder.add_testNumber(count);
        auto response = builder.Finish();
        fbb.Finish(response);

        // Send the flatbuffer
        std::cout << "Sending. " << count << ". ";
        int buffersize = fbb.GetSize();
        zmq::message_t message(buffersize);
        memcpy((void *)message.data(), fbb.GetBufferPointer(), buffersize);
        socket.send(message);
        std::cout << "Sent. ";

        // Receive reply
        zmq::message_t reply;
        socket.recv(&reply);

        // Read the data
        auto inmsg = flatbuffer::GetTestBuf(&reply);
        std::cout << " Received reply: " << inmsg << std::endl;

        //auto num = inmsg->testNumber();
        //std::cout << num << " test number.";
    }
    return 0;
}

This code runs fine and displays (I think) the raw buffer each program is receiving. Strangely, it is not changing, although the content of the message should be. If I uncomment the last two lines and try to access inmsg->testNumber(), I get this error message:

Unhandled exception at 0x000000013F373C53 in KUKAREQ.exe: 0xC0000005: Access violation reading location 0x00000000004B35D8.

I have sent Flatbuffers objects through ZMQ successfully before, but I have not read them in C++. I am fairly sure I followed the Flatbuffers tutorial closely, but something is obviously going wrong. Pointers? Buffer sizes? Either way I would appreciate help.


Edit: To clarify my comment on the accepted answer, the offending line was:

auto inmsg = flatbuffer::GetTestBuf(&reply);

It has to be changed to:

auto inmsg = flatbuffer::GetTestBuf(reply.data());

Whoever reads this question may also be interested to know that I later came across a bug which occurs when the FlatBufferBuilder functions are not called in the correct order. Apparently the order in which the Flatbuffers object is built is important. Finding that one took me a while - novices watch out.


回答1:


Not familiar with ZeroMQ, but flatbuffer::GetTestBuf(&request) this looks problematic.. you need to pass the buffer, not the message structure. Likely request.data() or similar works better.

In general, if it crashes in FlatBuffers, you should use the verifier to verify the buffer you're passing to FlatBuffers. If that fails, it means you're not passing legal data to FlatBuffers, as is the case here.

Also, you may want to check if ZeroMQ can send buffers without copying, will be faster.



来源:https://stackoverflow.com/questions/35975442/reading-flatbuffers-objects-sent-via-zmq-in-c-throws-unhandled-exception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!