2014-11-16 2 views
0

C++ protobuf에서 반복되는 두 필드의 직렬화에 이상한 문제가 있습니다. 연습을 위해 시계열 데이터를 선택하고 앱에서 직렬화/비 직렬화를 시도했습니다. 내가 (전체 요점 참조) 하나 개의 .cpp 파일에 오류를 재현, 여기에 파일을 protobuf 쓰는 핵심 아이디어 독서는 예로부터 그것을 가지고 : 잘 작동Protobuf 반복 필드 deserialization

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 

synthetic_control_TRAIN 파일을 시간 시리즈를, 당신은 https://yadi.sk/d/gxZy8JSvcjiVD

여기에서 얻을 수 있습니다

내 시스템 : g ++ 4.8.1, 우분투 12.04, libprotobuf 2.6.1

+0

'protoc --decode'를 사용하여 쉘에서 데이터를 디코딩 할 수 있습니다. 문제가 인코딩에 있는지 또는 디코딩 측면에 있는지를 적어도 알 수 있어야합니다. – jpa

답변

1

데이터의 크기는 얼마나됩니까? 보안을 위해 CodedInputStream의 기본값은 64MiB로 제한되며 그 이후에는 더 많은 데이터를 읽지 않습니다. CodedInputStream::SetTotalBytesLimit()을 사용하여 한도를 늘릴 수 있지만 더 좋은 해결책은 신선한 메시지 CodedInputStream을 사용하여 각 메시지를 읽는 것입니다. 이 클래스는 생성 및 삭제가 빠르기 때문에 스택에 할당하고 메시지 하나를 읽은 다음 범위를 벗어난다. 당신이 Protobuf 자바하지만 Protobuf-C++에 존재하는 parseDelimitedFrom() 형식을 모방하려는처럼

BTW, 보이는 (하지 마십시오.하지만, 기본 ZeroCopyInputStream 재 할당),하지만 코드가 기록으로 - 매우 효율적이지 않습니다. 스택에 각 메시지의 불필요한 복사본을 만들고 있습니다. my code from this StackOverflow answer을 사용해보십시오.