簡體   English   中英

Protobuf重復字段反序列化

[英]Protobuf repeated fields deserialization

我在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返回,則消息將包含具有丟失值和null的重復字段數組。 序列化階段應該沒問題,我已經檢查了所有內容。

您能否說,我做錯了嗎?

完整的要點可以從這里獲得: 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

您可以從這里獲取具有時間序列的Composite_control_TRAIN文件https://yadi.sk/d/gxZy8JSvcjiVD

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

您的數據有多大? 為了安全起見, CodedInputStream默認為CodedInputStream的限制,此后它將拒絕讀取更多數據。 您可以使用CodedInputStream::SetTotalBytesLimit()增加限制,但是更好的解決方案是使用新的CodedInputStream讀取每個消息。 該類的構造和銷毀速度很快,因此只需將其分配在堆棧上,讀取一條消息,然后使其超出范圍。 (不過,不要重新分配基礎的ZeroCopyInputStream 。)

順便說一句,您似乎正在嘗試仿效Protobuf-Java中存在的parseDelimitedFrom()格式,而不是Protobuf-C ++中存在的格式,但是您編寫的代碼效率不高:您正在對每個消息進行不必要的復制堆棧。 考慮使用我的StackOverflow答案中的代碼

暫無
暫無

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

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