PHP中字符串的内部表示形式


Internal representation of strings in PHP

我正在用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编码(cyrillic),因此它包含对UTF-8无效的符号。这可能会导致mb_strpos以某种方式尝试转换或仅使用额外的内存来满足某些需求。将尝试在mb_strpos的来源中找到答案。

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

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

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

mb_strpos()函数使用mbfl_strpos(),当它必须执行转换(如您所观察到的,导致内存增加)时,它会复制字符串(针、草堆):https://github.com/php/php-src/blob/master/ext/mbstring/libmbfl/mbfl/mbfilter.c#L811

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

值得一试:)