2012-12-12 19 views
8

Otrzymuję to ostrzeżenie i błąd później, gdy próbuję analizować dużą wiadomość. Wiem niż 64 MB, który jest domyślnym limitem. Używam wiadomości.ParseFromIstream teraz. Czy ktoś wie, aby uzyskać dostęp do obiektu CodedInputStream, aby wywołać funkcję SetTotalBytesLimit? lub w inny sposób rozwiązać ten problem?Jak zmienić limit bufora w Google protobuf?

Odczytywanie niebezpiecznie dużego komunikatu protokołu. Jeśli komunikat okaże się, że jest większy niż 67108864 bajtów, parsowanie zostanie zatrzymane dla celów bezpieczeństwa . Aby zwiększyć limit (lub wyłączyć te ostrzeżenia), zobacz CodedInputStream :: SetTotalBytesLimit() w google/protobuf/io/coded_stream.h.

Odpowiedz

8

Poprawna poprawka: Powinieneś spróbować ograniczyć rozmiary swoich komunikatów protobuf. Proszę zobaczyć: https://developers.google.com/protocol-buffers/docs/techniques#streaming

Podejście szybkie i brudne (czytaj nie zalecane): W coded_stream.h plików źródła biblioteki Protobuf, zmienić wartości od kDefaultTotalBytesLimit i kDefaultTotalBytesWarningThreshold, skompilować i zainstalować ponownie.

+2

Zamiast proponować zarządzanie własną gałęzią kodu protobuf (ugh), można po prostu ręcznie skonstruować CodedInputStream i użyć tego. Ponowne zaprojektowanie aplikacji będzie najprawdopodobniej najlepszą opcją, ale nie ma absolutnie żadnego powodu, aby utrzymywać własny oddział. – Voo

+0

Szybkie i brudne podejście zadziałało dla mnie. Dzięki. –

8

tylko czytanie dokumentacji funkcji, że błąd już mówiłem o, to już odpowiedział na to pytanie:

Podpowiedź: Jeśli czytasz to, ponieważ program drukuje ostrzeżenie o niebezpiecznie duże komunikaty protokołu, możesz być zdezorientowany o tym, co robić dalej. Najlepszym rozwiązaniem jest zmiana projektu, takiego jak , że nadmiernie duże wiadomości nie są konieczne. Na przykład spróbuj zastosować formaty plików projektowych , aby składać się z wielu małych wiadomości, a nie z jednego dużego, większego niż . Jeśli nie jest to możliwe, należy zwiększyć limit . Istnieje jednak szansa, że ​​twój kod nigdy nie zbuduje CodedInputStream, na którym można ustawić limit. Prawdopodobnie parsujesz wiadomości , nazywając takie rzeczy jak Message :: ParseFromString(). W tej przypadku, będziesz musiał zmienić swój kod, aby zamiast tego skonstruować jakiś rodzaj ZeroCopyInputStream (np. ArrayInputStream), skonstruować wokół niego kodowany InputInputStream , a następnie wywołać Message :: ParseFromCodedStream(). Następnie możesz dostosować limit . Tak, to więcej pracy, ale robisz coś niezwykłego.

Source

Także to chyba naprawdę dobry pomysł, aby śledzić pierwszą część porad i przeprojektowanie aplikacji.

+0

Mój obecny projekt jest taki. Mam wiadomość obrazkową, która ma wiele rzeczy.Oprócz tego mam ImageSet z powtarzającym się obrazem. Każdy ImageSet jest zapisywany do pliku i mam kilka ImageSetów ze względu na rozmiary plików. Czy istnieje lepszy sposób to zrobić? –

+1

Nie do końca jasne, co robisz, ale osobiście zrobiłbym tak, aby ImageSet zawierał tylko odniesienia do rzeczywistych obrazów, co spowodowałoby dość małą wiadomość. Oczywiście jedna wiadomość na obraz, która również nie powinna być nigdzie bliska granicy 65 MB. Możesz nadal przechowywać wszystko w jednym pliku bez dodatkowej pracy. Chociaż nie jestem pewien, dlaczego używasz protobuf, a nie DB, jeśli wszystko, co robisz, to przechowuj je w lokalnym FS. – Voo

+0

Mój program to aplikacja naukowa, w której analizuję obrazy i zapisuję wyniki w plikach itp. Dlatego właśnie komunikat Obraz staje się bardzo duży. –

3

Here's a comment from the code (google/protobuf/io/coded_stream.h), która ustawia limit wiadomości dla tych, którzy zastanawiają się, z jakiego powodu bezpieczeństwa mówią. W moim przypadku nie mogę zmienić sposobu działania mojej aplikacji, więc muszę zmienić ten limit.

Ten wątek jest dość stary, ale ostatnio głębokie uczenie się przykuło uwagę, a biblioteka Caffe użyła Protobufa, więc może więcej osób natknę się na to. Muszę robić rzeczy z sieci neuronowej za pomocą Caffe, a cała sieć zajmowała tyle pamięci, nawet przy najmniejszym rozmiarze wsadu.

// Total Bytes Limit ----------------------------------------------- 
    // To prevent malicious users from sending excessively large messages 
    // and causing integer overflows or memory exhaustion, CodedInputStream 
    // imposes a hard limit on the total number of bytes it will read. 

    // Sets the maximum number of bytes that this CodedInputStream will read 
    // before refusing to continue. To prevent integer overflows in the 
    // protocol buffers implementation, as well as to prevent servers from 
    // allocating enormous amounts of memory to hold parsed messages, the 
    // maximum message length should be limited to the shortest length that 
    // will not harm usability. The theoretical shortest message that could 
    // cause integer overflows is 512MB. The default limit is 64MB. Apps 
    // should set shorter limits if possible. If warning_threshold is not -1, 
    // a warning will be printed to stderr after warning_threshold bytes are 
    // read. For backwards compatibility all negative values get squashed to -1, 
    // as other negative values might have special internal meanings. 
    // An error will always be printed to stderr if the limit is reached. 
    // 
    // This is unrelated to PushLimit()/PopLimit(). 
    // 
    // Hint: If you are reading this because your program is printing a 
    // warning about dangerously large protocol messages, you may be 
    // confused about what to do next. The best option is to change your 
    // design such that excessively large messages are not necessary. 
    // For example, try to design file formats to consist of many small 
    // messages rather than a single large one. If this is infeasible, 
    // you will need to increase the limit. Chances are, though, that 
    // your code never constructs a CodedInputStream on which the limit 
    // can be set. You probably parse messages by calling things like 
    // Message::ParseFromString(). In this case, you will need to change 
    // your code to instead construct some sort of ZeroCopyInputStream 
    // (e.g. an ArrayInputStream), construct a CodedInputStream around 
    // that, then call Message::ParseFromCodedStream() instead. Then 
    // you can adjust the limit. Yes, it's more work, but you're doing 
    // something unusual. 
Powiązane problemy