PHP中字符串的内部表示

时间:2012-08-25 20:19:30

标签: php string memory

我正在PHP 5.2.10上编写一个简单的网站解析器 使用默认内部编码(ISO-8859-1)时,我总是在同一个函数调用中得到一个错误:

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

致命错误:允许的内存大小为50331648字节(尝试分配11924760字节)

在这种情况下,字符串$ index的长度为2981190字节 - 恰好是PHP尝试分配的4倍。

现在,如果我使用

mb_internal_encoding('UTF-8')

错误消失。这是否意味着PHP为多字节字符串使用更多内存用于单字节字符串?怎么可能?有什么想法吗?

UPD:内存使用似乎不依赖于编码:使用UTF-8和ISO-8859-1,平均memory_get_usage()几乎相同。我认为问题可能在于mb_strpos。 实际上,字符串$ index具有Windows-1251编码(西里尔文),因此它包含对UTF-8无效的符号。这可能导致mb_strpos以某种方式尝试转换或仅使用额外的内存来满足某些需求。 将尝试在mb_strpos的源代码中找到答案。

1 个答案:

答案 0 :(得分:3)

很抱歉,如果您已经考虑过这些潜在问题。

多字节字符串函数将检查UTF-8编码是否有错误,如果有无效字符,则返回空字符串或false(如mb_strpos()的情况: http://www.serverphorums.com/read.php?7,552099

您是否使用===运算符检查结果,以确保您没有收到false而不是0

mb_strpos()函数使用mbfl_strpos(),它在必须执行转换时生成字符串(needle,haystack)的副本(导致内存增加,如您所观察到的): https://github.com/php/php-src/blob/master/ext/mbstring/libmbfl/mbfl/mbfilter.c#L811

所以,我想知道是否使用默认内部编码(ISO-8859-1)让一切都通过,并且内存限制被命中,而utf-8编码由于非法字符而短路并返回false(如果您使用==进行测试,则会使该函数看起来只是找不到匹配项。)

值得一试:)