Переполнение стека в boost::regex_match
От: igna Россия  
Дата: 18.04.08 09:36
Оценка:
Проверяю строку состоящую из 10000 a и одного b на соответствие регулярному выражению a*b , regex_match возвращает true. Заменяю выражение на (a)*b , в regex_match бросает исключение runtime_error. Смотрю, оказывается происходит переполнение стека. Замена (a)*b на (?:a)*b не помогает. Как же быть, если нужно записать что-то вроде (a|c)*b ?

int main()
{
    int const n = 10000;
    char s[n];
    std::fill_n(s, n, 'a');
    s[n] = 'b';
    s[n + 1] = '\0';

    boost::regex e("(?:a)*b");
    bool b = boost::regex_match(s, e);

    return 0;
}



22.04.08 02:12: Перенесено модератором из 'C/C++' — Кодт
Re: Переполнение стека в boost::regex_match
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.08 09:39
Оценка:
Здравствуйте, igna, Вы писали:

I>Проверяю строку состоящую из 10000 a и одного b на соответствие регулярному выражению a*b , regex_match возвращает true. Заменяю выражение на (a)*b , в regex_match бросает исключение runtime_error. Смотрю, оказывается происходит переполнение стека. Замена (a)*b на (?:a)*b не помогает. Как же быть, если нужно записать что-то вроде (a|c)*b ?

попробуй
"(?:a|c)*b"
"[ac]*b"
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Переполнение стека в boost::regex_match
От: igna Россия  
Дата: 18.04.08 09:49
Оценка:
Здравствуйте, jazzer, Вы писали:

J>"(?:a|c)*b"

J>"[ac]*b"

Первое не помогает, а второе на самом деле не подходит, я проблему не точно описал. Уточняю: (a|cd)*b
Re: Переполнение стека в boost::regex_match
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.08 09:58
Оценка:
Здравствуйте, igna, Вы писали:

I>Проверяю строку состоящую из 10000 a и одного b на соответствие регулярному выражению a*b , regex_match возвращает true. Заменяю выражение на (a)*b , в regex_match бросает исключение runtime_error. Смотрю, оказывается происходит переполнение стека. Замена (a)*b на (?:a)*b не помогает. Как же быть, если нужно записать что-то вроде (a|c)*b ?


I>
I>int main()
I>{
I>    int const n = 10000;
I>    char s[n];
I>}
I>

ну, вообще-то у тебя стек может исчерпаться уже вот здесь.
тебе обязательно нужно такой здоровенный массив держать на стеке?
Попробуй смеху ради вынести его за пределы функции, или превратить в std::vector — исправится положение?

З.Ы. у меня на 64-битной машине твой код сработал без проблем
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re: Переполнение стека в boost::regex_match
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.08 10:01
Оценка: 35 (3)
Здравствуйте, igna, Вы писали:

I>Проверяю строку состоящую из 10000 a и одного b на соответствие регулярному выражению a*b , regex_match возвращает true. Заменяю выражение на (a)*b , в regex_match бросает исключение runtime_error. Смотрю, оказывается происходит переполнение стека. Замена (a)*b на (?:a)*b не помогает. Как же быть, если нужно записать что-то вроде (a|c)*b ?


Еще посмотри сюда, если тебе позарез нужна такая дурища на стеке:
http://www.boost.org/doc/libs/1_35_0/libs/regex/doc/html/boost_regex/configuration/algorithm.html
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[2]: Переполнение стека в boost::regex_match
От: igna Россия  
Дата: 18.04.08 10:15
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Попробуй смеху ради вынести его за пределы функции, или превратить в std::vector — исправится положение?


Нет.

int main()
{
    int const n = 10000;
    std::vector<char> s(n + 1 + 1);
    std::fill(s.begin(), s.begin() + n, 'a');
    s[n] = 'b';
    s[n + 1] = '\0';

    boost::regex e("(?:a|cd)*b");
    bool b = boost::regex_match(s.begin(), e);

    return 0;
}
Re: Поправка
От: igna Россия  
Дата: 18.04.08 10:18
Оценка:
Вместо

    char s[n];


должно быть

    char s[n + 2];


Но по случайности это ничего не меняло, a*b работало, а (a)*b — нет. Как до, так и после исправления.
Re[2]: Переполнение стека в boost::regex_match
От: igna Россия  
Дата: 18.04.08 10:27
Оценка:
Здравствуйте, jazzer, Вы писали:

J>http://www.boost.org/doc/libs/1_35_0/libs/regex/doc/html/boost_regex/configuration/algorithm.html


non-stack recursive matching algorithm ... always safe no matter how pathological the regular expression


Спасибо. Попробую для моего "патологического" выражения (a|cd)*b .

Хотя стек-не стек, работы для regex_match выражение (a)*b или (?:a)*b задает похоже значительно больше. Хотелось бы понять, почему.
Re[3]: Добавление
От: igna Россия  
Дата: 18.04.08 10:29
Оценка:
Больше чем a*b .
Re[3]: Переполнение стека в boost::regex_match
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.08 10:32
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, jazzer, Вы писали:


J>>http://www.boost.org/doc/libs/1_35_0/libs/regex/doc/html/boost_regex/configuration/algorithm.html


I>

I>non-stack recursive matching algorithm ... always safe no matter how pathological the regular expression


I>Спасибо. Попробую для моего "патологического" выражения (a|cd)*b .


I>Хотя стек-не стек, работы для regex_match выражение (a)*b или (?:a)*b задает похоже значительно больше. Хотелось бы понять, почему.


Ну, почему первое — понятно, это же capturing-скобки (как по-русски это будет, есть термин?), а вот со вторым — действительно непонятно, должно быть то же самое, что из без скобок вообще.

У тебя какая версия буста, кстати?
Попробуй последнюю, если сработает, значит, был баг и его пофиксили.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Переполнение стека в boost::regex_match
От: igna Россия  
Дата: 18.04.08 10:51
Оценка:
Здравствуйте, jazzer, Вы писали:

J>У тебя какая версия буста, кстати?

J>Попробуй последнюю, если сработает, значит, был баг и его пофиксили.

1.34.1, то есть почти самая последняя. Зато VC++ 6.0.

Если это баг в Boost.Regex, то это странно. На ровном месте ведь. Я в регулярных выражениях новичок и надеялся, что я сам что-нибудь неправильно сделал. Например, что нужно не (a)*b , а ^(a)*b$ или (a)*?b .
Re[5]: Переполнение стека в boost::regex_match
От: jazzer Россия Skype: enerjazzer
Дата: 18.04.08 11:35
Оценка:
Здравствуйте, igna, Вы писали:

I>Здравствуйте, jazzer, Вы писали:


J>>У тебя какая версия буста, кстати?

J>>Попробуй последнюю, если сработает, значит, был баг и его пофиксили.

I>1.34.1, то есть почти самая последняя. Зато VC++ 6.0.


I>Если это баг в Boost.Regex, то это странно. На ровном месте ведь. Я в регулярных выражениях новичок и надеялся, что я сам что-нибудь неправильно сделал. Например, что нужно не (a)*b , а ^(a)*b$ или (a)*?b .


ну, скобки с захватом точно использовать не нужно, если тебе не нужен захват. Если нужны скобки для группировки, используй незахватывающие "(?".
Потом, если ты можешь привязать свой регексп к началу или концу строки, то лучше это делать хотя бы из соображений скорости.
Хотя, может, regex_match эту привязку делает автоматически, но все равно, лучше убедиться экспериментально.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[5]: И в VC++ 7.1 тоже
От: igna Россия  
Дата: 19.04.08 07:33
Оценка:
При замене VC++ 6.0 на VC++ 7.1 ничего не изменилось.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.