Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

preg_match "вылетает", если совпадение превышает 8000 барьер (Алексей Харьков, оценка: 4)
Author Message
Алексей Харьков
Guest





Карма: 386
   поощрить/наказать


PostPosted: Thu Sep 24, 2009 1:47 pm (написано за 5 минут 33 секунды)
   Post subject: preg_match "вылетает", если совпадение превышает 8000 барьер
Reply with quote

Составил регулярное выражение
Code (php): скопировать код в буфер обмена
$pattern = '#(?:</?br style="clear: left[^>]*>)((?!<\/div>\r?\n<div class=line>).)*#is';
Ищется все, что находится между <br style="clear:left"> и <\div>перевод строки <\div class=line>. Все работает нормально, НО, если длина найденной строки превышает 8036 символов (зависит от того, каких символов большеЖкириллицы или латиницы, так что думаю не совсем удачная единица измерения - символы - но отклонения от 8036 +/- небольшие) выдается совершенно пустая страница (даже не выдает все что идет перед и после preg_match). На локальном сервере все работает норм. В чем может быть проблема?
Back to top
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Thu Sep 24, 2009 4:29 pm (спустя 2 часа 41 минуту; написано за 2 минуты 23 секунды)
   Post subject:
Reply with quote

в мануале, в начале раздела PCRE, висит варнинг со ссылкой, открываем её и читаем:
Quote:
The maximum length of a compiled pattern is 65539 (sic) bytes if PCRE
       is compiled with the default internal linkage size of 2
Предполагаю, что если internal linkage size выставить в 1, то будет как раз объем в 8Кб. Чем выше число, тем длиннее могут быть строки и тем медленнее они обрабатываются. Используйте другой алгоритм.
Back to top
View user's profile Send private message
Алексей Харьков
Guest





Карма: 386
   поощрить/наказать


PostPosted: Thu Sep 24, 2009 4:39 pm (спустя 10 минут; написано за 14 секунд)
   Post subject:
Reply with quote

Дедо в том, что я пробовал дописывать символы ДО <br style="clear:left"> или ПОСЛЕ <\div class=line>, и функция срабаывала, если длина совпадения была меньше 8Кб... Как узнать nternal linkage size?
Back to top
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 195
   поощрить/наказать

Location: 007 495

PostPosted: Thu Sep 24, 2009 5:15 pm (спустя 35 минут; написано за )
   Post subject:
Reply with quote

Посмотрите флаги компиляции в phpinfo(), там это должно быть отражено. В любом случае, если Вашу задачу можно решить без регов, то, вероятно, при таких объемах совпадений лучше так и сделать.
Back to top
View user's profile Send private message Send e-mail
dimagolov
Участник форума



Joined: 04 Feb 2007
Posts: 1664
Карма: 96
   поощрить/наказать

Location: Christ Church, Barbados

PostPosted: Thu Sep 24, 2009 9:11 pm (спустя 3 часа 55 минут; написано за 4 минуты 32 секунды)
   Post subject:
Reply with quote

Алексей Харьков, во-первых ознакомьтесь с phpfaq.ru/debug и вместо "выдается совершенно пустая страница" выясните какая конкретно ошибка происходит.

п.с. у меня была такая ошибка:
Quote:
PHP Warning: preg_match() [<a href='function.preg-match'>function.preg-match</a>]: Get subpatterns list failed in D:\Local\htdocs\Work_d\include\lib\mimeDecode.php on line 401
в ф-ии
Code (php): скопировать код в буфер обмена
    function _splitBodyHeader($input)
    {
        if (preg_match (www.php.net/preg_match)("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
            return array (www.php.net/array)($match[1], $match[2]);
        }
        $this->_error = 'Could not split header and body';
        return false;
    }
которая фактически делила email на заголовки и тело. происходило это при обработке сообщения с аттачем на 13.3 метра. решением было изменение лимитов:
Code (php): скопировать код в буфер обмена
ini_set (www.php.net/ini_set)('memory_limit', '160M'); // 128 по-моему не хватало
ini_set (www.php.net/ini_set)('pcre.backtrack_limit', '5000000'); // 1000000 было мало
 
память понятно что в начале тоже вылетала, когда оно перестало вылетать по памяти, то началось то, что я написал выше.
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Fri Sep 25, 2009 5:54 am (спустя 8 часов 43 минуты; написано за 5 минут 48 секунд)
   Post subject:
Reply with quote

оффтопик:
dimagolov
по RFC в письмах используется исключительно \r\n . Так что делить лучше через explode().

И вообще:
оценивать расход ресурсов - весьма полезно. И менять алгоритм в случае перерасхода на более сложный, но экономный - имхо, тоже полезно. Например, в случае топикстартера я бы привел переносы к единому виду (\r\n -> \n), делил тем же explode и разбирался с кусочками
Back to top
View user's profile Send private message
dimagolov
Участник форума



Joined: 04 Feb 2007
Posts: 1664
Карма: 96
   поощрить/наказать

Location: Christ Church, Barbados

PostPosted: Fri Sep 25, 2009 9:07 pm (спустя 15 часов 13 минут; написано за 9 минут 58 секунд)
   Post subject:
Reply with quote

Maus, согласен, но тут у меня был выбор:
1. Копаться в нутрях либы, выяснять как она реагирует на не-RFC корректные письма и оптимизировать ее по использованию памяти, что даст реальный эфект в < 5% случаях, то есть работы на несколько дней + тестирования хотя-бы месяц на живой системе и реальных письмах, так как иначе всего разнообразия того, что может прийти от отправителей я не придумаю
2. Подправить лимиты, чтобы хватило для обработки рельно полученного письма, потребность в коротых проявится в < 5% случаях и не переживать за то, что ранее имевшееся поведение может измениться и то, раньше корректно обрабатывалось может перестать, на это ушло 10 минут работы.

Я не против оптимизиции, я против нее тогда, когда она не оправданна. Как только я буду получать столько больших писем, что их обработка будет нагружить сервер, я ей обязательно займусь. Только не думаю, что это случиться в ближайшие пару лет :)

Кстати, приведение писем в RFC вид без pcre как бы не тривиально, а если хоть раз пропускаешь большое письмо через pcre, то backtrack_limit надо менять. Позволить себе дропать не-RFC я не могу и так или иначе должен их обрабатывать.
Quote:
случае топикстартера я бы привел переносы к единому виду (\r\n -> \n), делил тем же explode и разбирался с кусочками
а еще надо учесть, что переносы могли быть \r и их тоже поменять на \n, а потом \n поменять обратно на \r\n чтобы соответствовало RFC? :)
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Sat Sep 26, 2009 2:14 am (спустя 5 часов 6 минут; написано за 6 минут 55 секунд)
   Post subject:
Reply with quote

dimagolov wrote:
не-RFC корректные письма
А такие существуют? И умудряются ходить между серверами? Или у Вас всё взаимодействие - между собственными сервисами?
Дима вон однажды ошибся в почтовой заглушке - письма сразу стали нечитаемыми генерироваться.
dimagolov wrote:
а еще надо учесть, что переносы могли быть \r
Ну, если внешний источник - то да, можно рассчитывать и на мак. Но всё равно только 2 прогона: \r\n ->\n и \r->\n (последовательность имеет значение).
dimagolov wrote:
потом \n поменять обратно на \r\n чтобы соответствовало RFC?
Не нужно - это ж HTML, а не письма. Там нет такого (точнее, есть, но только в заголовках и опять же без вариантов - \n, кажется)
Back to top
View user's profile Send private message
NikolayV
Заглянувший



Joined: 20 Sep 2010
Posts: 3
Карма: 0
   поощрить/наказать


PostPosted: Mon Sep 20, 2010 2:25 pm (спустя 11 месяцев 24 дня 12 часов 11 минут; написано за 6 минут 28 секунд)
   Post subject: Апач вылетает при использовании сложных PCRE
Reply with quote

У меня вылетает Апач при использовании preg_match с такими условиями:
Code (php): скопировать код в буфер обмена
$result =
Code (html): скопировать код в буфер обмена
        <tr> (december.com/html/4/element/tr.html)
            <td (december.com/html/4/element/td.html) style="WIDTH: 50%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)Size</strong></td>
            <td (december.com/html/4/element/td.html) style="WIDTH: 25%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)S</strong></td>
            <td (december.com/html/4/element/td.html) style="WIDTH: 25%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)M</strong></td>
            <td> (december.com/html/4/element/td.html)L</td>
            <td> (december.com/html/4/element/td.html)XL</td>               
            <td> (december.com/html/4/element/td.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)&nbsp;M</font></td>
            <td> (december.com/html/4/element/td.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)&nbsp;L</font></td>
           <td> (december.com/html/4/element/td.html)
            <p (december.com/html/4/element/p.html) align="center"> (december.com/html/4/element/.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)&nbsp;One Size</strong></font></p>
           </td>
        </tr>
        <tr> (december.com/html/4/element/tr.html)
            <td (december.com/html/4/element/td.html) style="WIDTH: 50%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)Pieces</strong></td>
            <td (december.com/html/4/element/td.html) style="WIDTH: 25%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)3</strong></td>
            <td (december.com/html/4/element/td.html) style="WIDTH: 25%"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)3</strong></td>
            <td> (december.com/html/4/element/td.html)3</td>
            <td> (december.com/html/4/element/td.html)1</td>
            <td> (december.com/html/4/element/td.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)&nbsp;1</font></td>
            <td> (december.com/html/4/element/td.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)&nbsp;1</font></td>
            <td> (december.com/html/4/element/td.html)
              <p (december.com/html/4/element/p.html) align="center"> (december.com/html/4/element/.html)<font (december.com/html/4/element/font.html) size="2"> (december.com/html/4/element/.html)<strong> (december.com/html/4/element/strong.html)&nbsp;4</strong></font></p>
            </td>
        </tr>
Code (php): скопировать код в буфер обмена
//Sizes
function getSizes($result){
        $out = array (www.php.net/array)();
        $parts = array (www.php.net/array)('Size','Pieces');
        $i = 0;
        foreach($parts as $part){
                $pattern = '/<td(.*?)('.$part.')+(.*?)<\/td>(([\n]*?)*(.*?)*)*<\/tr>/';
                $pattern2 = '/<td(.*?)>(<(.*?)>)*([\s]*(&nbsp;)*)*(.*?)([\s]*(&nbsp;)*)*(<(.*?)>)*<\/td>/';
                preg_match (www.php.net/preg_match)($pattern,$result,$match);
                preg_match_all (www.php.net/preg_match_all)($pattern2,$match[0],$match2);
                print_r (www.php.net/print_r)($match2);
                $args[$i] = $match2[5];
                $i++;
        }
        if( $args[0][0] == "Size" && $args[1][0] == "Pieces" ) {
                array_shift (www.php.net/array_shift)($args[0]);
                array_shift (www.php.net/array_shift)($args[1]);
        }
        for( $i = 0; $i < count (www.php.net/count)($args[0]); $i++ ){
                $out[$args[0][$i]] = $args[1][$i];
        }
        return $out;
}
print_r (www.php.net/print_r) ( getSizes($result) );
Соответственно, Апач выпадает в сообщение Windows (Vista) о закрытии данного приложения.

Если из каждого <tr> таблицы убрать последние строки (там где есть \n <p>), все нормально срабатывает.

P.S.: Выдача в поток произойти не успевает, и, видимо, поэтому я не вижу никакой ошибки PHP.
error_reporting E-ALL
set_time_limit(0)
Back to top
View user's profile Send private message
NikolayV
Заглянувший



Joined: 20 Sep 2010
Posts: 3
Карма: 0
   поощрить/наказать


PostPosted: Mon Sep 20, 2010 2:42 pm (спустя 16 минут; написано за 16 секунд)
   Post subject:
Reply with quote

Не знаю, вероятно будет полезно:
Quote:
Сигнатура проблемы:
  Имя события проблемы: APPCRASH
  Имя приложения: httpd.exe
  Версия приложения: 2.2.4.0
  Штамп времени приложения: 45a476e3
  Имя модуля с ошибкой: php5ts.dll
  Версия модуля с ошибкой: 5.2.12.12
  Штамп времени модуля с ошибкой: 4b291270
  Код исключения: c00000fd
  Смещение исключения: 0015181f
  Версия ОС: 6.0.6002.2.2.0.768.3
  Код языка: 1049
  Дополнительные сведения 1: ce16
  Дополнительные сведения 2: 66b0df064fd5c5f2376a115b922f4999
  Дополнительные сведения 3: bfb7
  Дополнительные сведения 4: 05bc6db6f310c3279f2ef8b5d4a454b5
Back to top
View user's profile Send private message
NikolayV
Заглянувший



Joined: 20 Sep 2010
Posts: 3
Карма: 0
   поощрить/наказать


PostPosted: Mon Sep 20, 2010 3:39 pm (спустя 56 минут; написано за 2 минуты 59 секунд)
   Post subject:
Reply with quote

Насколько я понимаю, в моем случае достигается предел итераций в самой ОС. Никто не знает как можно решить эту проблему? Правка PCRE в php.ini ничего не дает, как только количество совпадений по шаблону становится больше определенного значения, Windows закрывает Апач. В частности, это воспроизводится простым добавлением строк <td>...</td> в таблицу, что я предоставил выше.
Back to top
View user's profile Send private message
Maus
Модератор



Joined: 29 Jun 2003
Posts: 8151
Карма: 271
   поощрить/наказать

Location: пос. Омсукчан Магаданской области

PostPosted: Tue Sep 21, 2010 3:43 am (спустя 12 часов 4 минуты; написано за 38 секунд)
   Post subject:
Reply with quote

NikolayV
М, если PHP как модуль, то после правки надо рестартовать Апач, не забыли?
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic All times are GMT + 3 Hours
Page 1 of 1    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML