在 C++ 中读取通过 ZMQ 发送的 Flatbuffers 对象会引发未处理的异常
Reading Flatbuffers objects sent via ZMQ in C++ throws unhandled exception
我正在尝试通过 ZMQ 通过网络发送一个相当大的 Flatbuffers 对象,然后使用 C++ 读取它。访问对象时,出现未处理的异常,我不知道如何解决。即使是这个最小的例子也失败了:
平面缓冲区架构:
namespace flatbuffer;
table TestBuf {
testStatus:bool;
testNumber:double;
testInt:int;
}
root_type TestBuf;
main.cpp 使用 REP 套接字:
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;
}
main.cpp 使用 REQ 套接字:
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 tutorial,但显然出了问题。指针?缓冲区大小?无论哪种方式,我都将不胜感激。
编辑:为了澄清我对已接受答案的评论,违规行是:
auto inmsg = flatbuffer::GetTestBuf(&reply);
必须改为:
auto inmsg = flatbuffer::GetTestBuf(reply.data());
阅读此问题的人可能也有兴趣知道我后来遇到了一个错误,该错误是在未按正确顺序调用 FlatBufferBuilder 函数时发生的。显然,构建 Flatbuffers 对象的顺序很重要。找到那个花了我一段时间 - 新手注意。
不熟悉 ZeroMQ,但是 flatbuffer::GetTestBuf(&request)
这看起来有问题。您需要传递缓冲区,而不是消息结构。可能 request.data()
或类似的效果更好。
一般来说,如果它在 FlatBuffers 中崩溃,您应该使用验证器来验证您传递给 FlatBuffers 的缓冲区。如果失败,则意味着您没有将合法数据传递给 FlatBuffers,就像这里的情况一样。
此外,您可能想检查 ZeroMQ 是否可以在不复制的情况下发送缓冲区,这样会更快。
我正在尝试通过 ZMQ 通过网络发送一个相当大的 Flatbuffers 对象,然后使用 C++ 读取它。访问对象时,出现未处理的异常,我不知道如何解决。即使是这个最小的例子也失败了:
平面缓冲区架构:
namespace flatbuffer;
table TestBuf {
testStatus:bool;
testNumber:double;
testInt:int;
}
root_type TestBuf;
main.cpp 使用 REP 套接字:
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;
}
main.cpp 使用 REQ 套接字:
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 tutorial,但显然出了问题。指针?缓冲区大小?无论哪种方式,我都将不胜感激。
编辑:为了澄清我对已接受答案的评论,违规行是:
auto inmsg = flatbuffer::GetTestBuf(&reply);
必须改为:
auto inmsg = flatbuffer::GetTestBuf(reply.data());
阅读此问题的人可能也有兴趣知道我后来遇到了一个错误,该错误是在未按正确顺序调用 FlatBufferBuilder 函数时发生的。显然,构建 Flatbuffers 对象的顺序很重要。找到那个花了我一段时间 - 新手注意。
不熟悉 ZeroMQ,但是 flatbuffer::GetTestBuf(&request)
这看起来有问题。您需要传递缓冲区,而不是消息结构。可能 request.data()
或类似的效果更好。
一般来说,如果它在 FlatBuffers 中崩溃,您应该使用验证器来验证您传递给 FlatBuffers 的缓冲区。如果失败,则意味着您没有将合法数据传递给 FlatBuffers,就像这里的情况一样。
此外,您可能想检查 ZeroMQ 是否可以在不复制的情况下发送缓冲区,这样会更快。