gpt4 book ai didi

c++ - Protobuf重复字段反序列化

转载 作者:太空宇宙 更新时间:2023-11-04 11:25:02 34 4
gpt4 key购买 nike

我在 C++ protobuf 中对重复双字段的序列化遇到了一个奇怪的问题。为了练习,我选择了时间序列数据并尝试在我的应用程序中进行序列化/反序列化。我在一个 .cpp 文件中重现了错误(请参阅完整要点),阅读编写 protobuf 文件的核心思想是从示例中获取的:

void writeMessage(::google::protobuf::Message &message) {
google::protobuf::uint32 size = message.ByteSize();
char buffer[size];
if(!message.SerializeToArray(buffer, size)) {
cerr << "Failed to serialize message: \n" << message.DebugString();
terminate();
}
codedOut->WriteVarint32(size);
codedOut->WriteRaw(buffer, size);
}
bool readMessage(::google::protobuf::Message &message) {
google::protobuf::uint32 size;
if (!codedIn->ReadVarint32(&size)) {
return false;
}
char buffer[size];

if(!codedIn->ReadRaw(buffer, size)) {
cerr << "Can't do ReadRaw of message size " << size << "\n";
terminate();
}
message.ParseFromArray(buffer, size);
return true;
}

对于 1-20 条消息,它工作正常,但如果我尝试读取 50 条或更多条消息,那么最后一条消息将被破坏——ReadRaw 将返回 false。如果我尝试忽略 ReadRaw 返回,则消息将包含带有缺失值和空值的重复字段数组。序列化阶段应该没问题,我已经检查了一切。

请问我是不是做错了什么?

您可以从这里获得完整的要点: https://gist.github.com/alexeyche/d6af8a43d346edc12868

要重现错误,您只需要做:

protoc -I. --cpp_out=. ./time_series.proto
g++ main.cpp time_series.pb.cc -std=c++11 -L/usr/local/lib -lprotobuf -I/usr/local/include
./a.out synthetic_control_TRAIN out.pb

带有时间序列的synthetic_control_TRAIN文件,你可以从这里得到 https://yadi.sk/d/gxZy8JSvcjiVD

我的系统:g++ 4.8.1,ubuntu 12.04,libprotobuf 2.6.1

最佳答案

您的数据有多大?为了安全起见,CodedInputStream 默认限制为 64MiB,超过之后它将拒绝读取更多数据。您可以使用 CodedInputStream::SetTotalBytesLimit() 增加限制,但更好的解决方案是使用新的 CodedInputStream 简单地读取每条消息。这个类的构造和销毁都很快,所以只需在堆栈上分配它,读取一条消息,然后让它离开范围。 (不过,不要重新分配底层的 ZeroCopyInputStream。)

顺便说一句,看起来您正在尝试模拟存在于 Protobuf-Java 而不是 Protobuf-C++ 中的 parseDelimitedFrom() 格式,但是您编写的代码效率不高:您' 在堆栈上制作每条消息的不必要拷贝。考虑使用 my code from this StackOverflow answer .

关于c++ - Protobuf重复字段反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26960906/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com