2012-08-25 12 views
6

Estoy escribiendo un analizador de sitios web simple en PHP 5.2.10.
Cuando se utiliza codificación interna por defecto (que es la norma ISO-8859-1), me sale un error siempre a la misma llamada de función:Representación interna de cadenas en PHP

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

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

La longitud del índice $ cadena en este caso fue 2981190 bytes: exactamente 4 veces menos de lo que PHP intentó asignar.

Ahora, si uso

mb_internal_encoding('UTF-8') 

el error desaparece. ¿Eso significa que PHP usa más memoria para cadenas de un solo byte que para cadenas de varios bytes? ¿Como es eso posible? ¿Algunas ideas?

UPD: El uso de la memoria no parece depender de la codificación: la memoria_get_usage() promedio es casi la misma usando UTF-8 e ISO-8859-1. Creo que el problema podría estar en mb_strpos. De hecho, el índice $ de cadena tiene codificación de Windows-1251 (cirílico), por lo que contiene símbolos que no son válidos para UTF-8. Esto puede causar que mb_strpos intente de alguna manera convertir o simplemente use la memoria adicional para algunas necesidades. Intentaremos encontrar la respuesta en las fuentes de mb_strpos.

+0

podría ayudar? http://www.php.net/manual/en/function.mb-strpos.php#81722 –

+0

¿ha considerado actualizar su PHP? En primer lugar porque 5.2 ya no es compatible, y en segundo lugar porque tanto las versiones 5.3 como 5.4 tuvieron mejoras significativas en el uso de la memoria (particularmente 5.3). No estoy seguro si esas mejoras incluyen 'mb_strpos()', pero vale la pena la actualización en cualquier caso. – Spudley

+0

Piensa que tu actualización está en el camino correcto. Varias cosas pueden influir ... mb_detect_order, uso de 'auto' o 'pass', por nombrar algunos. Usar 'iconv' puede ser una buena forma de asegurarse de que sus cadenas estén" cuerdas "y coincidan con la codificación detectada/establecida. Me gustaría hacer un perfil y ver qué está haciendo con esos 1252 códigos de control. Oh malvado m-dash. – ficuscr

Respuesta

3

Lo sentimos si ya ha pensado en estos posibles problemas.

Las funciones de cadenas multibyte comprobarán UTF-8 codificaciones de errores y, si hay caracteres no válidos, devuelve una cadena vacía o falsas (como en el caso de mb_strpos(): http://www.serverphorums.com/read.php?7,552099

¿Está la comprobación de la resultado que está recibiendo el uso del operador === para asegurarse de que usted no está recibiendo false en lugar de 0?

la función mb_strpos() utiliza mbfl_strpos(), lo que hace copias de las cuerdas (aguja, pajar) cuando tiene que realizar las conversiones (llevando a incrementos en la memoria, como usted observa d): https://github.com/php/php-src/blob/master/ext/mbstring/libmbfl/mbfl/mbfilter.c#L811

Por lo tanto, me pregunto si se utiliza la codificación predeterminada interna (ISO-8859-1) dejar que todo a través, y el límite de memoria fue golpeado, mientras que la codificación UTF-8 en cortocircuito debido a la caracteres ilegales y devuelto falsa (que, si estuviera probando con ==, sería hacer que parezca que la función meramente no se encontró una coincidencia.)

Vale la pena probarlo :)

+0

¡Una buena foto! Para comprobar si el resultado es 'falso' o' 0', he escrito una función similar 'assert()', la comprobación se realiza estrictamente (===). Pero ahora no entiendo por qué PHP necesita 4 veces la memoria strlen, de hecho, convierte ambos argumentos en UTF-8 (y no en 'mb_internal_encoding()'). ¡Gracias por su investigación y las fuentes adjuntas! ;) – Dmitry

Cuestiones relacionadas