2012-08-25 23 views
6

我在PHP 5.2.10上编写了一个简单的网站解析器。
当使用默认的内部编码(这是ISO-8859-1),我得到一个错误总是在同一个函数调用:在PHP中的字符串的内部表示形式

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

Fatal error: Allowed memory size of 50331648 bytes exhausted (tried to allocate 11924760 bytes)

字符串$指数在这种情况下,长度为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的来源中找到答案。

+0

可能有助于? http://www.php.net/manual/en/function.mb-strpos.php#81722 –

+0

你有考虑升级你的PHP吗?首先,因为5.2不再被支持,其次,因为5.3和5.4版本都有显着的内存使用改进(特别是5.3)。不知道这些改进是否包含'mb_strpos()',但在任何情况下都值得升级。 – Spudley

+0

认为你的更新是正确的。许多事情可能会影响...... mb_detect_order,使用'auto'或'pass'等等。使用'iconv'可以是确保你的字符串“健全”并匹配检测/设置编码的好方法。想要分析这些1252控制代码,看看它在做什么。哦,邪恶的M-DASH。 – ficuscr

回答

3

对不起,如果你已经想到了这些潜在的问题。

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

你检查导致你使用===运营商,以确保你不接收false代替0

mb_strpos()函数使用mbfl_strpos(),这使得(针,干草堆)字符串的副本时,它必须进行转换(得到正如你观察到的那样,导致记忆力增加所以,我想知道如果使用默认的内部编码(ISO-8859-1)让一切都通过,并且内存限制被击中,而utf-8编码短路由于非法字符并返回false(其中,如果你用==测试,会使其出现该功能只是没有找到一个匹配。)

值得一试:)

+0

一个不错的镜头! 为了检查结果是“假”还是“0”,我写了一个函数'assert()',严格执行检查(===)。 但现在我不明白为什么PHP需要4次strlen内存 - 实际上,它将两个参数都转换为UTF-8(而不是'mb_internal_encoding()')。 感谢您的研究和附加资料! ;) – Dmitry

相关问题