2012-12-12 15 views
8

Ricevo questo avviso e un errore in seguito quando cerco di analizzare un messaggio di grandi dimensioni. So che oltre 64 MB è il limite predefinito. Sto usando message.ParseFromIstream ora. Qualcuno sa di avere accesso all'oggetto CodedInputStream per chiamare la funzione SetTotalBytesLimit? o in altro modo per risolvere questo problema?Come modificare il limite del buffer nel protobuf di Google?

Lettura messaggio di protocollo pericolosamente grande. Se il messaggio risulta di dimensioni superiori a 67108864 byte, l'analisi verrà interrotta per motivi di sicurezza . Per aumentare il limite (o disabilitare questi avvisi), vedere CodedInputStream :: SetTotalBytesLimit() in google/protobuf/io/coded_stream.h.

risposta

8

La correzione corretta: si dovrebbe cercare di limitare le dimensioni dei messaggi protobuf. Si prega di vedere: https://developers.google.com/protocol-buffers/docs/techniques#streaming

L'(leggi non raccomandato) approccio veloce e sporco: Nel file coded_stream.h della sorgente della libreria protobuf, modificare i valori di kDefaultTotalBytesLimit e kDefaultTotalBytesWarningThreshold, ricompilare e reinstallare.

+2

Invece di proporre di gestire il proprio ramo del codice protobuf (ugh), si può semplicemente costruire manualmente il CodedInputStream e usarlo. La riprogettazione dell'applicazione sarebbe molto probabilmente l'opzione migliore, ma non c'è assolutamente alcun motivo per mantenere la propria filiale. – Voo

+0

L'approccio rapido e sporco ha funzionato per me. Grazie. –

8

Basta leggere la documentazione della funzione che l'errore già ti ha parlato, avrebbe mai risposto a questa domanda:

Suggerimento: Se stai leggendo questo perché il programma sta stampando un avvertimento circa messaggi di protocollo pericolosamente grandi, potresti essere confuso con su cosa fare dopo. L'opzione migliore è quella di cambiare il tuo design come che i messaggi troppo grandi non sono necessari. Ad esempio, prova a creare formati di file di progettazione composti da molti piccoli messaggi anziché da uno singolo di dimensioni . Se ciò non è possibile, è necessario aumentare il limite . Tuttavia, è probabile che il tuo codice non costruisca mai un CodedInputStream su cui è possibile impostare il limite. Probabilmente analizzi i messaggi chiamando cose come Message :: ParseFromString(). In questo caso , dovrai modificare il tuo codice per costruire un po 'di tipo di ZeroCopyInputStream (ad esempio un ArrayInputStream), costruire un CodedInputStream, quindi chiamare Message :: ParseFromCodedStream(). Quindi puoi regolare il limite . Sì, è più lavoro, ma stai facendo qualcosa di insolito.

Source

Inoltre è probabilmente una buona idea di seguire la prima parte del consiglio e riprogettare l'applicazione.

+0

Il mio attuale design è così. Ho un messaggio di immagine che ha un sacco di cose.In aggiunta a ciò ho ImageSet che ha un'immagine ripetuta in esso. Ogni ImageSet è scritto su un file e ho diversi ImageSet a causa delle dimensioni dei file. C'è un modo migliore per farlo? –

+1

Non esattamente chiaro cosa stai facendo, ma personalmente lo farei in modo che ImageSet contenga solo riferimenti alle immagini reali, il che renderebbe un messaggio abbastanza piccolo. Ovviamente un messaggio per immagine che non dovrebbe essere neanche vicino al limite di 65MB. Puoi ancora memorizzarlo tutto in un unico file senza molto lavoro extra. Anche se non sono sicuro del motivo per cui stai usando protobuf e non un DB se tutto ciò che fai è archiviarlo nelle FS locali. – Voo

+0

Il mio programma è un'applicazione scientifica in cui sto analizzando immagini e salvando risultati in file, ecc. Ecco perché un messaggio Image diventa molto grande. –

3

Here's a comment from the code (google/protobuf/io/coded_stream.h) che imposta il limite di messaggi per coloro che si chiedono quale sia il motivo di sicurezza di cui stanno parlando. Nel mio caso non posso modificare il modo in cui funziona la mia applicazione, quindi devo modificare questo limite.

Questo thread è piuttosto vecchio, ma recentemente l'apprendimento approfondito ha attirato l'attenzione e la libreria Caffe ha utilizzato Protobuf quindi forse più persone inciamperanno su questo. Devo fare cose di rete neurale con Caffe, e l'intera rete ha preso così tanta memoria anche con le dimensioni di batch più piccole.

// 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. 
Problemi correlati