簡體   English   中英

在 C++ 中讀取通過 ZMQ 發送的 Flatbuffers 對象拋出未處理的異常

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

我正在嘗試通過 ZMQ 通過網絡發送一個相當大的 Flatbuffers 對象,然后使用 C++ 讀取它。 訪問對象時,我遇到了未處理的異常,我不知道如何解決。 即使這個最小的例子也失敗了:

flatbuffers 架構:

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

使用 REP 套接字的 main.cpp:

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;
}

使用 REQ 套接字的 main.cpp:

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;
}

這段代碼運行良好並顯示(我認為)每個程序正在接收的原始緩沖區。 奇怪的是,它並沒有改變,盡管消息的內容應該改變。 如果我取消對最后兩行的注釋並嘗試訪問 inmsg->testNumber(),則會收到以下錯誤消息:

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

我之前通過 ZMQ 成功發送過 Flatbuffers 對象,但我沒有用 C++ 讀取它們。 我相當確定我密切關注Flatbuffers 教程,但顯然有些地方出了問題。 指針? 緩沖區大小? 無論哪種方式,我都會很感激幫助。


編輯:為了澄清我對已接受答案的評論,違規行是:

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

它必須改為:

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

讀過這個問題的人可能也有興趣知道我后來遇到了一個錯誤,當 FlatBufferBuilder 函數沒有以正確的順序調用時會發生這個錯誤。 顯然,Flatbuffers 對象的構建順序很重要。 找到那個花了我一段時間 - 新手要小心。

不熟悉 ZeroMQ,但flatbuffer::GetTestBuf(&request)這看起來有問題..你需要傳遞緩沖區,而不是消息結構。 可能request.data()或類似的效果更好。

通常,如果它在 FlatBuffers 中崩潰,您應該使用驗證器來驗證您傳遞給 FlatBuffers 的緩沖區。 如果失敗,則意味着您沒有將合法數據傳遞給 FlatBuffers,就像這里的情況一樣。

此外,您可能想檢查 ZeroMQ 是否可以在不復制的情況下發送緩沖區,這樣會更快。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM