使用 preg_match 或 preg_match_all 處理超長字串 (如完整 HTML 頁面、大型 JSON) 時,函式回傳 false 且無錯誤訊息,實際上是觸發了 PCRE 回溯限制。
PHP 5.2.0 引入 pcre.backtrack_limit (預設 100,000) 限制正則引擎回溯次數,防止惡意正則導致 CPU 耗盡。超過限制時匹配直接失敗。
// 在執行正則前調大限制 (視記憶體而定)
ini_set('pcre.backtrack_limit', 1000000); // 100 萬
ini_set('pcre.recursion_limit', 100000); // 遞迴限制,防止堆疊溢位
// 建議同時限制記憶體
ini_set('memory_limit', '256M');
| 參數 | 預設值 | 作用 | 調整建議 |
|---|---|---|---|
| pcre.backtrack_limit | 100000 | 最大回溯步數 | 長字串匹配失敗時調大,但過大導致 CPU 飆高 |
| pcre.recursion_limit | 100000 | 最大遞迴深度 | 配合 backtrack_limit 調整,過大導致 PHP 崩潰 |
| memory_limit | 128M | 腳本記憶體上限 | 確保有足夠緩衝處理大字串 |
.* 貪婪匹配,改用 .*? 或具體字元類別 [^<>]*。ini_set,避免影響全域。$result = @preg_match($pattern, $longString);
if ($result === false) {
$error = preg_last_error();
if ($error === PREG_BACKTRACK_LIMIT_ERROR) {
error_log('PCRE backtrack limit exceeded');
} elseif ($error === PREG_RECURSION_LIMIT_ERROR) {
error_log('PCRE recursion limit exceeded');
}
}