Search code examples
phparraysstringreturnreturn-value

PHP Return Long String is not Usable as String


I am having a for loop which is iterating through a large array $result. Every array item $row is used to generate a new line of string $line. This string is concatenated into $str. To preserve memory, I am using unset($result[$i]) to clear every array item that has been processed in the original array. This looks like this:

$resultcount = count($result);
for($i=0; $i<$resultcount; ++$i){
   $row = $result[$i];

   $line = do_something($row);
   $str.= '<tr><td>'.$line.'</td></tr>';
   unset($result[$i]);
}

return $str;

This (more or less exotic piece of code) works unless the string exceeds a length of approx. 1'000'000 characters. In this case the return value is just empty. This is highly irritating because:

  1. The calculation effort (in this example do_something()) is not a problem. By using echo count($result).' - '.strlen($str)."\n" I can see that the loop finishes properly. There is no web server or php error shown.
  2. The memory_limit is also not a problem. I am working with more data on other parts of the application.

It appears that the problem lies in return $str itself. If I am using return substr($str, 0, 980000) then it just works fine. Further debugging shows that the string gets tainted as soon as it reaches the length of 999'775 bytes.

I can't put longer return value string into another string variable. But I am able to do a strlen() to get a proper result (1310307). So the return value string has a total length of 1'310'307 bytes. But I can't use them properly as a string.

Where does this limitation come from and how may I circumvent it?


Solution

  • Well, it took me two and a half year to figure this out ;(

    Rarst was right: It was not a problem of the function compiling and delivering the string. Later in the process I was using preg_replace() to do some further replacements. This function is not able to handle long strings. This could be fixed by using ini_set('pcre.backtrack_limit', 99999999999) beforehand as mentioned in How to do preg_replace on a long string