7

PHP 5.2.10 で簡単な Web サイト パーサーを作成しています。
デフォルトの内部エンコーディング (ISO-8859-1) を使用すると、常に同じ関数呼び出しでエラーが発生します。

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

致命的なエラー: 50331648 バイトの許容メモリ サイズが使い果たされました (11924760 バイトを割り当てようとしました)

この場合の文字列 $index の長さは 2981190 バイトで、PHP が割り当てようとした長さのちょうど 4 分の 1 です。

今、私が使用する場合

mb_internal_encoding('UTF-8')

エラーが消えます。これは、PHP がマルチバイト文字列よりもシングルバイト文字列により多くのメモリを使用するということですか? それはどのように可能ですか?何か案は?

UPD: メモリ使用量はエンコーディングに依存していないようです: 平均的な memory_get_usage() は、UTF-8 と ISO-8859-1 を使用してほぼ同じです。問題は mb_strpos にあるのではないかと思います。実際、文字列 $index には Windows-1251 エンコーディング (キリル文字) が使用されているため、UTF-8 に対して無効な記号が含まれています。これにより、mb_strpos が何らかの形で変換を試みたり、必要に応じて追加のメモリを使用したりする可能性があります。mb_strpos のソースで答えを見つけようとします。

4

1 に答える 1

3

これらの潜在的な問題についてすでに考えていた場合は、申し訳ありません。

マルチバイト文字列関数は UTF-8 エンコーディングのエラーをチェックし、無効な文字がある場合は空の文字列または false を返します (mb_strpos() の場合のように: http://www.serverphorums.com/read.php? 7,552099

の代わりに===受け取っていないことを確認するために、演算子を使用して取得している結果をチェックしていますか?false0

この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 を返しました (これは、でテストして==いた場合、関数が単に一致を見つけられなかったように見えます。)

試してみる価値 :)

于 2012-08-29T05:41:45.117 に答える