2013-07-10 12 views
12

strlen($str) sta tornando valori negativi per un "enorme stringa" che viene creato utilizzando str_repeat:Perché PHP strlen() restituisce una lunghezza negativa?

<?php 

error_reporting(E_STRICT|E_ALL); 
echo phpversion(); // 5.3.26 
echo PHP_INT_MAX; // 9223372036854775807 
ini_set('memory_limit', '-1'); 
ini_set('max_execution_time', 0); 

$gb = 1024 * 1024 * 1024; 
$str = str_repeat('a', 2 * $gb); 
echo strlen($str); // gives int(-2147483648) 
echo $str[0]; // Notice: Uninitialized string offset: 0 

$str2 = str_repeat('a', 4 * $gb); 
echo strlen($str2); // gives int(0) 

$str3 = str_repeat('a', 123 + 4 * $gb); 
echo strlen($str3); // gives int(123) 

$str4 = str_repeat('a', 6 * $gb); // starts to wrap again... 
echo strlen($str4); // gives int(-2147483648) 
echo $str4[0]; // Notice: Uninitialized string offset: 0 

$str5 = str_repeat('a', 123 + 8 * $gb); 
echo strlen($str5); // gives int(123) 

?> 

È questo il comportamento definito?

Oppure si tratta di un bug PHP?

+0

Sembra che tu abbia eseguito il valore intero massimo su PHP a 32 bit. Un server a 64 bit riporterebbe la lunghezza esatta. – ceejayoz

+3

Come strlen restituisce un valore intero e tutti gli interi in PHP sono interi con segno e PHP a 32 bit utilizza numeri interi con segno a 32 bit, quindi viene definito implicitamente. La costante PHP_INT_MAX ti dà il limite superiore, dopo di che il valore "avvolge" e diventa negativo –

+0

I miei rapporti PHP_INT_MAX 9223372036854775807 ... – Pacerier

risposta

5

string can be as large as 2GB.

Sembra che sia in effetti (2 GB - 1). Questo funziona bene sulla mia macchina x64:

$str = str_repeat('a', 2 * 1024 * 1024 * 1024 -1); 
echo $str[0]; 

... mentre questo si rompe:

$str = str_repeat('a', 2 * 1024 * 1024 * 1024); 
echo $str[0]; 

Quello che state facendo è semplicemente indefinita, e il manuale dovrebbe essere corretto. Mi sarei aspettato un avvertimento anche.

È interessante notare che questo solleva un errore fatale:

$str = str_repeat('a', 2 * 1024 * 1024 * 1024 -2); // 2GB - 2 bytes 
$str .= 'b'; // ok 
$str .= 'c'; // PHP Fatal error: String size overflow 


Aggiornamento:

Il bug report è stato curato. La documentazione su php.net è stata corretta e ora scrive "2147483647 byte al massimo".

+1

Ho seguito il tuo suggerimento e ho inviato la segnalazione di bug: https://bugs.php.net/bug.php?id=65239 – Pacerier

+0

Sì per qualche motivo anche se 'echo $ str [0];' non funziona, il la stringa prende ancora memoria e possiamo operare su di essa (usando il trim ecc.). – Pacerier

+0

@Pacerier È possibile aggiungere il caso di test con la concatenazione di stringhe alla segnalazione di bug, sembra supportare l'idea che si tratti di un bug di documentazione. Inoltre 'str_repeat' dovrebbe probabilmente lanciare lo stesso errore fatale di quando si concatena. – RandomSeed

2

Suppongo che tu stia semplicemente traboccando un int con la tua stringa di grandi dimensioni. Da un manuale:

The size of an integer is platform-dependent, although a maximum value of about two billion is the usual value (that's 32 bits signed). PHP does not support unsigned integers. Integer size can be determined using the constant PHP_INT_SIZE, and maximum value using the constant PHP_INT_MAX since PHP 4.4.0 and PHP 5.0.5.

Quindi dovrebbe essere OK se le dimensioni della stringa possono essere contenute in int.

+1

Non c'è overflow intero, il mio PHP_INT_MAX segnala 9223372036854775807 – Pacerier

+1

Leggi l'articolo [manuale per le stringhe] (http://php.net/language.types.string). Non importa quale sia il valore intero massimo se le stringhe hanno un limite diverso. – Gumbo

+0

@Gumbo, strlen() restituisce un int. Quindi sei limitato al limite int in quello che puoi restituire da strlen. Non importa quale limite hanno le stringhe. – Jk1

Problemi correlati