【问题标题】:Protobuf repeated fields deserializationProtobuf 重复字段反序列化
【发布时间】:2014-11-16 19:09:07
【问题描述】:

我在 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

【问题讨论】:

  • 您可以使用protoc --decode 在shell 中解码您的数据。这至少应该说明问题是在编码方面还是在解码方面。

标签: c++ serialization protocol-buffers


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2020-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-26
    • 1970-01-01
    • 2016-06-29
    相关资源
    最近更新 更多