2012-08-25 10 views
6

Sto scrivendo un semplice parser per siti web su PHP 5.2.10.
Quando si usa la codifica interno predefinito (che è ISO-8859-1), ottengo un errore sempre alla stessa chiamata di funzione:Rappresentazione interna di stringhe in PHP

$start = mb_strpos($index, '<a name=gr1>'); 

Fatal error: Allowed memory size of 50331648 bytes exhausted (tried to allocate 11924760 bytes)

La lunghezza della stringa $ indice in questo caso è stato 2.981.190 byte - esattamente 4 volte meno di PHP ha cercato di allocare.

Ora, se io uso

mb_internal_encoding('UTF-8') 

l'errore scompare. Ciò significa che PHP utilizza più memoria per stringhe a byte singolo che per multibyte? Com'è possibile? Qualche idea?

UPD: L'utilizzo della memoria non sembra dipendere dalla codifica: la media memory_get_usage() è quasi la stessa usando UTF-8 e ISO-8859-1. Penso che il problema potrebbe essere in mb_strpos. Infatti, la stringa $ index ha la codifica Windows-1251 (cirillico), quindi contiene simboli non validi per UTF-8. Questo potrebbe causare mb_strpos in qualche modo provare a convertire o semplicemente utilizzare la memoria aggiuntiva per alcune esigenze. Cercherò di trovare la risposta nei sorgenti di mb_strpos.

+0

potrebbe aiutare? http://www.php.net/manual/en/function.mb-strpos.php#81722 –

+0

hai considerato l'aggiornamento del tuo PHP? Innanzitutto perché 5.2 non è più supportato, e in secondo luogo perché entrambe le versioni 5.3 e 5.4 hanno avuto significativi miglioramenti nell'utilizzo della memoria (in particolare 5.3). Non sono sicuro se questi miglioramenti includano 'mb_strpos()', ma vale la pena di essere aggiornato in ogni caso. – Spudley

+0

Pensa che il tuo aggiornamento sia sulla buona strada. Un certo numero di cose potrebbe influenzare ... mb_detect_order, uso di 'auto' o 'pass', per nominarne alcuni. L'uso di 'iconv' può essere un buon modo per assicurarsi che le tue stringhe siano" sensate "e corrispondano alla codifica rilevata/impostata. Vorrei vedere e vedere cosa sta facendo con quei codici di controllo 1252. Oh cattiva m-dash. – ficuscr

risposta

3

Scusate se avete già pensato a questi potenziali problemi.

Le funzioni stringa multibyte controlleranno UTF-8 codifiche per gli errori e, se ci sono caratteri non validi, restituisce una stringa vuota o falso (come nel caso di mb_strpos(): http://www.serverphorums.com/read.php?7,552099

Stai controllando il risultato che stai ricevendo utilizzando l'operatore === per assicurarsi che non si sta ricevendo false invece di 0?

la funzione mb_strpos() usa mbfl_strpos(), che rende copie delle stringhe (aghi, Mucchio di fieno) quando deve eseguire conversioni (portando ad aumenti nella memoria, come si osserva d): https://github.com/php/php-src/blob/master/ext/mbstring/libmbfl/mbfl/mbfilter.c#L811

Quindi, mi chiedo se si utilizza la codifica interna di default (ISO-8859-1) lasciare tutto attraverso, e il limite di memoria è stato colpito, mentre la codifica UTF-8 cortocircuitato a causa della caratteri non validi e restituiti falsa (che, se si stesse provando con ==, farebbe sembrare che la funzione semplicemente non ha trovato una corrispondenza.)

pena un colpo :)

+0

Un bel colpo! Per verificare se il risultato è 'false' o' 0' ho scritto una funzione allo stesso modo 'assert()', il controllo viene eseguito rigorosamente (===). Ma ora non capisco perché PHP abbia bisogno di 4 volte memoria strlen - in effetti, converte entrambi gli argomenti in UTF-8 (e non un 'mb_internal_encoding()'). Grazie per la tua ricerca e le fonti allegate! ;) – Dmitry

Problemi correlati