Следующая функция прерывается с регулярным выражением, которое я предоставил в переменной $ pattern. Если я изменил regexp, я в порядке, поэтому я думаю, что это проблема. Я не вижу проблемы, хотя, и я не получаю стандартную ошибку PHP, даже если они включены.
function parseAPIResults($results){ //Takes results from getAPIResults, returns array. $pattern = '/\[(.|\n)+\]/'; $resultsArray = preg_match($pattern, $results, $matches); }
Firefox 6: соединение было сброшено
- как создать имя пользователя: пароль в файле .htpasswd на сервере Wamp, установленном на ОС Windows
- Как создать страницу 404 на сервере WAMP
- Почему я не могу проверить свои данные и зарегистрировать свои данные в базе данных?
- Как включить memcache в WAMP
- Как отправить электронную почту с локального сервера Wamp с помощью PHP?
Chrome 14: Ошибка 101 (net :: ERR_CONNECTION_RESET): соединение было сброшено.
IE 8: Internet Explorer не может отображать веб-страницу
ОБНОВИТЬ:
Apache / PHP может быть сбой. Вот журнал ошибок Apache при запуске скрипта:
[Сб Окт 01 11:41:40 2011] [уведомление] Родитель: дочерний процесс завершен со статусом 255 – Перезапуск.
[Сб окт 01, 11:41:40 2011] [уведомление] Apache / 2.2.11 (Win32) Настройка PHP / 5.3.0 – возобновление обычных операций
Запуск WAMP 2.0 в Windows 7.
Простой вопрос. Комплексный ответ!
Да, этот класс регулярных выражений будет повторяться (и молча) сбой Apache / PHP с необработанной ошибкой сегментации из-за переполнения стека!
Семейство регулярных выражений PHP preg_*
использует мощную библиотеку PCRE Филиппа Хейзеля. В этой библиотеке существует определенный класс регулярных выражений, который требует много рекурсивных вызовов для своей внутренней функции match()
и это использует много пространства стека (и используемое пространство стека прямо пропорционально размеру строки субъекта соответствие). Таким образом, если строка субъекта слишком длинная, произойдет переполнение стека и соответствующая ошибка сегментации. Такое поведение описано в документации PCRE в конце под рубрикой «pcrestack» .
pcre.recursion_limit
слишком большой. Документация PCRE описывает, как избежать ошибки сегментации переполнения стека, ограничивая глубину рекурсии до безопасного значения, примерно равного размеру стека связанного приложения, деленного на 500. Когда глубина рекурсии должным образом ограничена, как рекомендовано, библиотека не генерирует переполнение стека и вместо этого изящно выходит с кодом ошибки. В PHP эта максимальная глубина рекурсии задается с помощью переменной конфигурации pcre.recursion_limit
и (к сожалению) значение по умолчанию установлено равным 100 000. Это значение слишком много! Ниже приведена таблица безопасных значений pcre.recursion_limit
для различных размеров исполняемых стеков:
Stacksize pcre.recursion_limit 64 MB 134217 32 MB 67108 16 MB 33554 8 MB 16777 4 MB 8388 2 MB 4194 1 MB 2097 512 KB 1048 256 KB 524
Таким образом, для сборки Win32 веб-сервера Apache ( httpd.exe
), который имеет (относительно небольшой) размер стека 256 КБ, правильное значение pcre.recursion_limit
должно быть установлено равным 524. Это может быть выполнено с помощью следующей строки PHP-код:
ini_set("pcre.recursion_limit", "524"); // PHP default is 100,000.
Когда этот код добавляется к скрипту PHP, переполнение стека НЕ происходит, а вместо этого генерирует значимый код ошибки. То есть, СЛЕДУЕТ генерировать код ошибки! (Но, к сожалению, из-за другой ошибки PHP, preg_match()
не делает.)
preg_match()
не возвращает FALSE при ошибке. Документация PHP для preg_match()
говорит, что она возвращает FALSE при ошибке. К сожалению, в версиях PHP 5.3.3 и ниже есть ошибка ( # 52732 ), где preg_match()
НЕ возвращает FALSE
при ошибке (вместо этого он возвращает int(0)
, что является тем же значением, возвращаемым в случае несоответствия) , Эта ошибка была исправлена в PHP версии 5.3.4.
Предполагая, что вы продолжите использовать WAMP 2.0 (с PHP 5.3.0), решение должно учитывать оба вышеупомянутых ошибки. Вот что я бы рекомендовал:
pcre.recursion_limit
до безопасного значения: 524. preg_match()
возвращает что-либо, кроме int(1)
. preg_match()
возвращает int(1)
, то совпадение было успешным. preg_match()
возвращает int(0)
, то совпадение было либо неудачным, либо произошла ошибка. Ниже приведена модифицированная версия вашего сценария (предназначенная для запуска из командной строки), которая определяет длину строки темы, которая приводит к ошибке ограничения рекурсии:
<?php // This test script is designed to be run from the command line. // It measures the subject string length that results in a // PREG_RECURSION_LIMIT_ERROR error in the preg_match() function. echo("Entering TEST.PHP...\n"); // Set and display pcre.recursion_limit. (set to stacksize / 500). // Under Win32 httpd.exe has a stack = 256KB and 8MB for php.exe. //ini_set("pcre.recursion_limit", "524"); // Stacksize = 256KB. ini_set("pcre.recursion_limit", "16777"); // Stacksize = 8MB. echo(sprintf("PCRE pcre.recursion_limit is set to %s\n", ini_get("pcre.recursion_limit"))); function parseAPIResults($results){ $pattern = "/\[(.|\n)+\]/"; $resultsArray = preg_match($pattern, $results, $matches); if ($resultsArray === 1) { $msg = 'Successful match.'; } else { // Either an unsuccessful match, or a PCRE error occurred. $pcre_err = preg_last_error(); // PHP 5.2 and above. if ($pcre_err === PREG_NO_ERROR) { $msg = 'Successful non-match.'; } else { // preg_match error! switch ($pcre_err) { case PREG_INTERNAL_ERROR: $msg = 'PREG_INTERNAL_ERROR'; break; case PREG_BACKTRACK_LIMIT_ERROR: $msg = 'PREG_BACKTRACK_LIMIT_ERROR'; break; case PREG_RECURSION_LIMIT_ERROR: $msg = 'PREG_RECURSION_LIMIT_ERROR'; break; case PREG_BAD_UTF8_ERROR: $msg = 'PREG_BAD_UTF8_ERROR'; break; case PREG_BAD_UTF8_OFFSET_ERROR: $msg = 'PREG_BAD_UTF8_OFFSET_ERROR'; break; default: $msg = 'Unrecognized PREG error'; break; } } } return($msg); } // Build a matching test string of increasing size. function buildTestString() { static $content = ""; $content .= "A"; return '['. $content .']'; } // Find subject string length that results in error. for (;;) { // Infinite loop. Break out. $str = buildTestString(); $msg = parseAPIResults($str); printf("Length =%10d\r", strlen($str)); if ($msg !== 'Successful match.') break; } echo(sprintf("\nPCRE_ERROR = \"%s\" at subject string length = %d\n", $msg, strlen($str))); echo("Exiting TEST.PHP..."); ?>
Когда вы запускаете этот скрипт, он обеспечивает непрерывное считывание текущей длины строки темы. Если pcre.recursion_limit
остается с слишком высоким значением по умолчанию, это позволяет измерить длину строки, которая приводит к сбою исполняемого файла.
preg_match()
не смог вернуть FALSE
когда в библиотеке PCRE возникла ошибка. Эта ошибка, безусловно, ставит под вопрос LOT кода, который использует preg_match
! (Я обязательно сделаю инвентаризацию своего собственного PHP-кода.) httpd.exe
) построен со стекизацией 256 КБ. Исполняемый файл командной строки PHP ( php.exe
) построен со стекированием 8 МБ. Безопасное значение для pcre.recursion_limit
должно быть установлено в соответствии с исполняемым файлом, что сценарий запускается в соответствии с (524 и 16777 соответственно). pcre.recursion_limit
по умолчанию для безопасного значения. preg_match()
к PHP версии 5.2. httpd.exe
исполняемого файла Apache httpd.exe
. (Это работает под XP, но Vista и Win7 могут жаловаться.) Я столкнулся с той же проблемой. Большое спасибо за ответ, отправленный ridgerunner.
Хотя полезно знать, почему сбой php, для меня это на самом деле не решает проблему. Чтобы решить проблему, мне нужно настроить мое регулярное выражение, чтобы сохранить память, чтобы php больше не разбивался.
Поэтому вопрос заключается в том, как изменить регулярное выражение. Ссылка на приведенное выше руководство PCRE уже описывает решение для примера regex, которое очень похоже на ваше.
Итак, как исправить ваше регулярное выражение? Во-первых, вы говорите, что хотите сопоставить «a. Или новую строку». Обратите внимание, что "." является особым символом в регулярном выражении, который не только соответствует точке, но и любому персонажу, поэтому вам нужно избежать этого. (Надеюсь, я не ошибся здесь, и это было предназначено.)
$pattern = '/\[(\.|\n)+\]/';
Затем мы можем скопировать квантификатор внутри скобок:
$pattern = '/\[(\.+|\n+)+\]/';
Это не меняет значения выражения. Теперь мы используем притяжательные кванторы вместо обычных:
$pattern = '/\[(\.++|\n++)++\]/';
Таким образом, это должно иметь то же значение, что и исходное регулярное выражение, но работать на php, не разбивая его. Зачем? Потенциальные кванторы «съедают» персонажей и не позволяют отступать. Поэтому PCRE не нужно использовать рекурсию, и стек не будет переполняться. Использование их внутри скобок кажется хорошей идеей, так как нам часто не нужна количественная оценка альтернативы.
Подводя итог, лучшая практика выглядит следующим образом:
Следуя этим правилам, я смог исправить свою собственную проблему, и я надеюсь, что это поможет кому-то другому.
У меня была одна и та же проблема, и вам нужно привязать шаблон к чему-то вроде
$pattern = '|/your pattern/|s';
«S» на конце в основном означает рассматривать строку как одну строку.
preg_match возвращает количество совпадений, найденных для шаблона. Если у вас есть совпадение, это приводит к фатальной ошибке в php (например, print_r(1)
, вызывает ошибку). print_r (0) (если вы меняете шаблон и не имеете совпадений) не выводит и не выводит 0.
Вы хотите print_r($matches)
Как в сторону, ваш шаблон не сбежал должным образом. Использование двойных кавычек означает, что вам нужно избежать обратных косых черт перед вашими скобками.