strlen($str)
возвращает отрицательные значения для "огромной строки", которая создается с помощью str_repeat
:
<?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)
?>
Определено ли это поведение?
Или это ошибка PHP?
Ответ 1
string
может достигать 2 ГБ.
Похоже, что это на самом деле (2GB - 1). Это отлично работает на моем поле x64:
$str = str_repeat('a', 2 * 1024 * 1024 * 1024 -1);
echo $str[0];
... пока это прерывается:
$str = str_repeat('a', 2 * 1024 * 1024 * 1024);
echo $str[0];
То, что вы делаете, просто undefined, и руководство должно быть исправлено. Я бы тоже ожидал предупреждения.
Интересно, что это приводит к фатальной ошибке:
$str = str_repeat('a', 2 * 1024 * 1024 * 1024 -2); // 2GB - 2 bytes
$str .= 'b'; // ok
$str .= 'c'; // PHP Fatal error: String size overflow
Update:
В отчете сообщается об ошибке. Документация на php.net исправлена и теперь пишет "максимум 2147483647 байт".
Ответ 2
Я предполагаю, что вы просто переполняете int своей большой строкой. Из руководства:
Размер целого числа зависит от платформы, хотя максимальное значение около двух миллиардов - это обычное значение (это 32 бита). PHP не поддерживает целые числа без знака. Integer размер может быть определен с использованием константы PHP_INT_SIZE и максимального значения с использованием константы PHP_INT_MAX с PHP 4.4.0 и PHP 5.0.5.
Итак, это должно быть ОК, если ваш размер строки может поместиться в int.