Сергей М.
78 повідомлень
#16 років тому
Привет всем.

Есть тут спецы по Perl regexp, или я один здесь такой?
Я, правда, нашёл это в июле 2008-го, но должно быть ещё актуально. Интересно, что ошибка проявляется в простом коде.


print "Match" if 'ab' =~ /^a?(?=b)b/; # Not match, but must...

Также можно заменить ^ на \A и ? на *.
Это аналогичные ошибки:


print $& if 'ab' =~ /a?(?=b)b/;
print $& if 'ab' =~ /a*(?=b)b/;

Оба оператора печатают b, но должны выводить ab.
Я отправил письмо с этим на bugsperl.org и получил ответ:

I checked some old perl installations and it appears that the bug has
appeared somewhere between 5.005_03 and 5.6.1. On 5.005_03 all three
snippets behave as they should, whereas on 5.6.1 the behaviour is the
same as in the original message.

Т.е. эта ошибка давно сидит в ядре Перла и должна быть на всех платформах.
Находил также другие ошибки, но они в основном исправлены. Вот наиболее интересная: программка в 18 символов


map{while(1){}}@a;

вешала Perl при трансляции(!). Проверял под Windows и Unix. В версии 5.8.7 только исправили.
Как хорошо, что на Перле не пишут программ по управлению атомными электростанциями!
Тут М.
626 повідомлень
#16 років тому
Ну ошибки есть везде. До сих пор помню как на областной олимпиаде потратил час на то, чтобы понять что ошибка не у меня в программе, а в самом паскале (что-то там было с генерацией случайных чисел).

В 5.10 описанный глюк тоже присутствует.
Евгений О.
263 повідомлення
#16 років тому
Цитата ("Serg31416"):

...
Т.е. эта ошибка давно сидит в ядре Перла и должна быть на всех платформах.


Ну и что? Ошибки есть в любой мало-мальски сложной программе. Вопрос лишь в том, как часто они проявляются и насколько критичными могут быть последствия.

Цитата ("Serg31416"):
Вот наиболее интересная: программка в 18 символов


map{while(1){}}@a;


вешала Perl при трансляции(!). Проверял под Windows и Unix. В версии 5.8.7 только исправили.


Вообще-то, Perl это интерпретирующий язык, сказать где кончается фаза трансляции и начинается выполнение странслированного кода достаточно сложно, но вот при выполнении, эта программка действительно должна "вешать" (точнее - зацикливать) интерпретатор, поскольку оператор


while(1){};


как раз и предполагает бесконечное выполнение. Я сейчас проверил программку приведенную в оригинальном сообщении под Perl 5.8.9 (FreeBSD), как и следовало ожидать, интерпретатор "зациклился".

Цитата ("Serg31416"):
Как хорошо, что на Перле не пишут программ по управлению атомными электростанциями!


Хорошо не то, что на Perl не пишут программ по управлению атомными электростанциями, а то что люди, которые пишут программы по управлению АЭС не используют конструкций подобных приведенным выше. Кстати, я совсем не удивлюсь, если узнаю, что какие-то программы используемые при управлении АЭС написаны в том числе и на Perl.
Сергей М.
78 повідомлень
#16 років тому
> как раз и предполагает бесконечное выполнение. Я сейчас проверил программку приведенную в оригинальном сообщении под Perl 5.8.9 (FreeBSD), как и следовало ожидать, интерпретатор "зациклился".

Это я просто выкинул всё лишнее. В цикле ведь могут стоять операторы перехода, это на ошибку не влияет.
Смысл примера в том, что как только поставишь внутрь map цикл while(1), то при трансляции Perl зависает или зацикливается. От тела цикла while это не зависело. Когда я понял, что моя программка зависает ещё при трансляции, то было такое чувство, что я первый, кто поставил эти циклы один в другой.
В regex тоже ошибки элементарные, выражение простейшее.
Евгений О.
263 повідомлення
#16 років тому
Цитата ("Serg31416"):

Смысл примера в том, что как только поставишь внутрь map цикл while(1), то при трансляции Perl зависает или зацикливается. От тела цикла while это не зависело.


Возможно, описываемый Вами эффект связан с областью действия операторов перехода из цикла или с областью действия среды выполнения блока map: например, оператор next нельзя использовать для выхода из блока map. Если мы предположим, что блок map выполняется рекурсивным вызовом интерпретатора, то здесь возможно множество тонких эффектов связанных, именно, с операторами перехода и локальными контекстами.

Во всяком случае, следующий блок кода выполняется совершенно корректно на Perl 5.8.5 (linux/Mandriva):


@a=(1,2); $c=0;
map{ while(1) { print ++$c,"\n";
exit if ($c>=3);} } @a;


При выполнении печатается:

1
2
3


Цитата ("Serg31416"):

Когда я понял, что моя программка зависает ещё при трансляции, то было такое чувство, что я первый, кто поставил эти циклы один в другой.


Это не исключено. Скорее всего, стоявшую перед Вами задачу можно было решить с помощью другого, если не более эффективного, то хотя бы более "читаемого" кода.

Цитата ("Serg31416"):
В regex тоже ошибки элементарные, выражение простейшее.


Было бы интересно проверить эти же выражения в программе на C - возможно, что и perl и С и PHP и пр. используют для разбора регулярных выражений одну и то же библиотеку, pcre или что-нибудь в этом роде. Если эффект подтвердится, то ошибку надо устранять не в perl, а в этой библиотеке.

Ошибки есть всегда и везде, в любом компиляторе, интерпретаторе, библиотеке, где угодно. Искусство программирования состоит в том, чтобы писать программу таким образом, чтобы не натыкаться на эти ошибки.
Тут М.
626 повідомлень
#16 років тому
Нет, ну про искусство программирования вы загнули. Не в этом оно состоит, точно. То, про что вы пишите - просто опыт.
Николай М.
1895 повідомлень
#16 років тому
Ничего удивительного, в мире опен сорс часто такое встречается, и не всегда бистро исправляется, по простой причине - никто ничего не обязан. Недавно читал на securitylab, что обнаружен баг возрастом почти в 25 лет в FreeBSD, в библиотеке SAMBA, а это значит что исправлять прийдется почти всем unix/linux-подобным системам)
Тут М.
626 повідомлень
#16 років тому
Точнее ошибка в библиотеке *dir()
Самой самбе (т.е. нетбиосу) вряд ли есть 25 лет.