2010-07-06 48 views
59

¿Qué tan grande puede obtener un $variable en PHP? Intenté probar esto, pero no estoy seguro de tener suficiente memoria del sistema (~ 2 gb). Me imagino que tiene que haber algún tipo de límite. ¿Qué sucede cuando una cuerda se hace demasiado grande? ¿Está concatenado, o PHP lanza una excepción?¿Cuál es la longitud máxima de una cadena en PHP?

+5

¿Qué estás tratando de hacer? – Sarfraz

+0

@sAc Quiero saber más sobre PHP. Sé que no puedo usar php para operaciones pesadas de memoria debido a fugas de memoria graves. – rook

+1

En php7 están eliminando esta limitación: http://stackoverflow.com/a/31085071/1090562 –

Respuesta

88

http://php.net/manual/en/language.types.string.php dice:

Nota: A partir de PHP 7.0.0, no hay restricciones particulares con respecto a la longitud de una cadena de 64 bits se basa. En construye de 32 bits y en versiones anteriores, una cadena puede ser tan grande como hasta 2 GB (2147483647 bytes como máximo)

En PHP 5.x, las cadenas se limitan a 2 -1 bytes, porque el código interno registró la longitud en un entero de 32 bits con signo.


Puede sorber en el contenido de un archivo completo, por ejemplo, utilizando file_get_contents()

Sin embargo, un script PHP tiene un límite en el total de memoria que puede asignar a todas las variables en una ejecución del script dado, por lo tanto, esto también impone un límite a la longitud de una sola variable de cadena.

Este límite es la directiva memory_limit en el archivo de configuración php.ini. El límite de memoria predeterminado es 128 MB en PHP 5.2 y 8 MB en versiones anteriores.

Si no especifica un límite de memoria en su archivo php.ini, usa el predeterminado, que se compila en el binario de PHP. En teoría, puede modificar el origen y reconstruir PHP para cambiar este valor predeterminado.

Si especifica -1 como límite de memoria en su archivo php.ini, deja de verificarse y permite que el script use tanta memoria como el sistema operativo asignará. Este sigue siendo un límite práctico, pero depende de los recursos del sistema y la arquitectura.


Re comentario de @ C2:

Aquí está una prueba:

<?php 

-- limit memory usage to 1MB 
ini_set('memory_limit', 1024*1024); 

-- initially, PHP seems to allocate 768KB for basic operation 
printf("memory: %d\n", memory_get_usage(true)); 

$str = str_repeat('a', 255*1024); 
echo "Allocated string of 255KB\n"; 

-- now we have allocated all of the 1MB of memory allowed 
printf("memory: %d\n", memory_get_usage(true)); 

-- going over the limit causes a fatal error, so no output follows 
$str = str_repeat('a', 256*1024); 
echo "Allocated string of 256KB\n"; 
printf("memory: %d\n", memory_get_usage(true)); 
+0

Entonces, ¿cuál es la mejor manera de trabajar dentro del límite de memoria si realmente necesitamos cadenas largas? – Pacerier

+0

Cuando PHP.net indica "La cadena de notas puede ser tan grande como 2 GB". http://php.net/manual/en/language.types.string.php ¿significa que puede ir * más * 2GB? – Pacerier

+0

@Pacerier, buena captura! Esa nota no estaba en la página del manual cuando respondí esta pregunta por primera vez en 2010. Editaré mi respuesta más arriba. –

16

cadena puede ser tan grande como 2 GB.
Source

+7

Y el desarrollador puede ser despedido – James

4

longitud de la cadena de PHP está limitada por la forma como las cadenas están representados en PHP; la memoria no tiene nada que ver con eso.

Según phpinternalsbook.com, las cadenas se almacenan en struct {char * val; int len; } y dado que el tamaño máximo de un int en C es de 4 bytes, esto efectivamente limita el tamaño máximo de cadena a 2 GB.

+1

.. ¿por qué los f no usarían unsigned int aquí? no como una cuerda puede ser MENOR DE 0 BYTES DE LARGO: p – hanshenrik

+1

No es del todo correcto. 2GB es 31bits. Perdieron un poco al usar un tipo de datos firmado.Quizás esto fue para simplificar cosas como las comprobaciones de desbordamiento sin requerir un valor mayor o especifico (concat A + B, uint total = A.len + B.len, si es total> TYPE_MAX/2 luego error), no creo C permite una verificación de desbordamiento sin caer al ensamblaje. – jgmjgm

+0

@jgmjgm 2 GB en 31 bits, es porque el bit 32 es para el signo. Si hubiera sido "unsinged int len", entonces tendría 32bits y 4GB – Jack

2

La longitud máxima de una variable de cadena es solo 2GiB - (2^(32-1) bits). Las variables pueden abordarse en base a caracteres (8 bits/1 byte) y el direccionamiento se realiza mediante enteros con signo, razón por la cual el límite es lo que es. Las matrices pueden contener múltiples variables, cada una de las cuales sigue la restricción anterior, pero puede tener un tamaño acumulativo total hasta memory_limit al que también está sujeta una variable de cadena.

2

En un próximo nuevo php7 entre muchas otras características, que añade soporte para strings bigger than 2^31 bytes:

El apoyo a las cadenas con longitud> = 2^31 bytes de 64 bits se basa.

Lamentablemente no especificaron cuánto más grande puede ser.

+0

¿Quizás 2^63 - 1? Ni siquiera sé si esa cantidad de RAM está disponible en algún lado ... – hakre

+0

En teoría podría permitir 2^32 o 2^64. Por el motivo que sea, se utilizan ints o longs firmados. Debido a que esto rompería el código en muchos lugares (si len jgmjgm

+0

apuesto 0x7FFFFFFFFFFFFFFF o 9223372036854775807 bytes (o 9.2 exabyts), menos lo que PHP ya esté usando, menos lo que ASLR esté desperdiciando, porque, ya sabes, el espacio de la memoria virtual de 64 bits estaría agotado: D – hanshenrik

0

Para responder correctamente a esta pregunta, debe tener en cuenta los aspectos internos de PHP o el objetivo para el que está diseñado PHP.

Para responder a esta desde una perspectiva típica de Linux en x86 ...

Los tamaños de los tipos en C: https://usrmisc.wordpress.com/2012/12/27/integer-sizes-in-c-on-32-bit-and-64-bit-linux/

tipos utilizados en PHP para las variables: http://php.net/manual/en/internals2.variables.intro.php

cadenas son siempre 2GB ya que la longitud es siempre de 32bits y se desperdicia un bit porque usa int en lugar de uint. int no es práctico para longitudes superiores a 2 GB, ya que requiere un molde para evitar romper comparaciones aritméticas o "que". Es probable que el bit adicional se esté utilizando para comprobaciones de desbordamiento.

Extrañamente, las claves hash pueden ser compatibles internamente con 4 GB, ya que se usa uint aunque nunca lo puse a prueba. Las claves PHP hash tienen un +1 a la longitud de un byte nulo posterior que, según mi conocimiento, se ignora, por lo que puede que no se tenga que firmar para ese caso límite en lugar de permitir claves más largas.

Un sistema de 32 bits puede imponer más límites externos.

Cuestiones relacionadas