Форум программистов, компьютерный форум CyberForum.ru

Regex_replace краши - C++

Восстановить пароль Регистрация
 
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
15.07.2014, 02:04     Regex_replace краши #1
собственно есть набор строк поиска/замены. Не могу понять почему спотыкается на:
искомая строка: ^(\[TEMPLATE.*\])(\n)((.|\n)*?)(item=)(i_gold,)
замена: %%%%% %%%%%

Правила существенно обрезаны. Строка замены на краш не влияет. А вот с искомой какие-то чудеса творятся.
если меняем строку
^(\[TEMPLATE.*\])(\n)((.|\n)*?)(item=)(i_gold) - крашит.
^(\[TEMPLATE.*\])(\n)((.|\n)*?)(item=)(i_) - шуршит.

Если текст в котором ищем обрезать в до 500 строк - все шуршит в обоих случаях, заменяет.
C++
1
2
3
4
std::vector<std::vector<string> > matchAndRules;
....
std::regex rgExRule(matchAndRules[v][0], std::tr1::regex_constants::icase);
inputTextStr = std::regex_replace(inputTextStr, rgExRule, matchAndRules[v][1]);
Добавлено через 9 минут
При краше отладчик говорит(моя такое не понимать):
Необработанное исключение по адресу 0x0FCA3977 (msvcr120d.dll) в RegExpTXT.exe: 0xC00000FD: Stack overflow (параметры: 0x00000000, 0x001F2000).
ссылается на 262 строку dbgrpt.c
return _VCrtDbgReportT(nRptType,returnAddress,szFile,nLine,szModule,szFormat,arglist);

Спасибо.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
15.07.2014, 02:04     Regex_replace краши
Посмотрите здесь:

regex_replace Boost C++
Как предотвращать краши из-за HttpWebRequest-запросов Visual Basic .NET

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Renji
1535 / 983 / 241
Регистрация: 05.06.2014
Сообщений: 2,967
15.07.2014, 17:15     Regex_replace краши #2
При краше отладчик говорит(моя такое не понимать):
Говорит что стек переполнился. Иными словами, кто-то, где-то вошел в бесконечную рекурсию. Пересобрать в дебаг-сборке, запустить еще раз из отладчика и посмотреть на каком именно месте программа упадет.
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
15.07.2014, 20:56  [ТС]     Regex_replace краши #3
xthrow.cpp 53 строка(тут третья).
C++
1
2
3
4
5
CRTIMP2_PURE _NO_RETURN(__CLRCALL_PURE_OR_CDECL _Xregex_error(regex_constants::error_type _Code))
    {   // report a regex_error
    _THROW_NCEE(regex_error, _Code);
    }
_STD_END
И что мне это дало? Пока совсем не представляю куда копать.

Можно как-то вытащить строку с которой происходило сравнение и шаг в правиле поиска?

Добавлено через 12 минут
xthrow.cpp 54 строка(тут четвертая). Ошибся...
Renji
1535 / 983 / 241
Регистрация: 05.06.2014
Сообщений: 2,967
15.07.2014, 22:03     Regex_replace краши #4
И что мне это дало? Пока совсем не представляю куда копать.
Отладчик должен где-то рядышком показывать стек вызовов. Найди там собственноручно написанную процедуру и дважды кликни по ней. Куда после этого перебрасывает?
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
16.07.2014, 07:20  [ТС]     Regex_replace краши #5
кидает сюда:
C++
1
        inputTextStr = std::regex_replace(inputTextStr, rgExRule, matchAndRules[v][1]);
Собственно я и так знал, что крашит этот самый реплейс(см название темы). Почему крашит то? Что ему не так?
castaway
Эксперт С++
4848 / 2987 / 368
Регистрация: 10.11.2010
Сообщений: 11,028
Записей в блоге: 10
Завершенные тесты: 1
16.07.2014, 07:55     Regex_replace краши #6
Какой компилятор то?
Renji
1535 / 983 / 241
Регистрация: 05.06.2014
Сообщений: 2,967
16.07.2014, 08:15     Regex_replace краши #7
Собственно я и так знал, что крашит этот самый реплейс(см название темы). Почему крашит то? Что ему не так?
1) Посмотреть сколько всего строк болтается в стеке вызовов. Если буквально 100500, значит искать кривую рекурсию.
2) Посмотреть в отладчике размер matchAndRules (должен быть больше v), размер matchAndRules[v] (должен быть больше единицы) и содержимое matchAndRules[v][1].
3) Обрезать код до загрузки inputTextStr и выполнения inputTextStr = std::regex_replace(inputTextStr, rgExRule, matchAndRules.at(v).at(1)); Все остальное выкинуть.
Если после всего этого программа продолжает падать, остается лишь считать что кривая библиотека регэекспов.
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
17.07.2014, 12:43  [ТС]     Regex_replace краши #8
Цитата Сообщение от castaway Посмотреть сообщение
Какой компилятор то?
MSVS 2013
Цитата Сообщение от Renji Посмотреть сообщение
1) Посмотреть сколько всего строк болтается в стеке вызовов. Если буквально 100500, значит искать кривую рекурсию.
Где посмотреть?
Цитата Сообщение от Renji Посмотреть сообщение
3) Обрезать код до загрузки inputTextStr и выполнения inputTextStr = std::regex_replace(inputTextStr, rgExRule, matchAndRules.at(v).at(1)); Все остальное выкинуть.
Если после всего этого программа продолжает падать, остается лишь считать что кривая библиотека регэекспов.
Обрезал до:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>
#include <ctime>
 
#include <regex>
#include <string>
 
#include <fstream>
#include <iomanip>
 
#include <vector>
 
using namespace std;
 
int main()
{
    setlocale(LC_ALL, "RUS");
 
 
    string inputTextStr; // строка
 
    ifstream inputTextFile; inputTextFile.open("I:\\Downloads\\RegExp\\inputText.txt", ios::binary);
    if (inputTextFile.good())
    {
        inputTextFile.seekg(0, ios::end);
        inputTextStr.resize(inputTextFile.tellg());
        inputTextFile.seekg(0, ios::beg);
 
        inputTextFile.read((char*)inputTextStr.data(), inputTextStr.size());
        inputTextFile.close();
    }
 
    cout << "1:\n";
    string str1 = "\\]((.|\\n)*?)(ITEM=tm_)";
    string str2 = "%%%%% %%%%%";
    std::regex rgExRule(str1, std::tr1::regex_constants::icase);
    inputTextStr = std::regex_replace(inputTextStr, rgExRule, str2);
    cout << inputTextStr;
    cin.get();
}
Опытным путем установлено, что конструкция ((.|\\n)*?) приводит к крашам за исключением очень коротких файлов в пару десятков строк. Чем больший кусок текста охватывает правило, тем меньший должен быть по размеру файл. Что собственно очень хорошо вписывается в краши ((.|\\n)*?). Там размер какого-нибудь буфера не ограничен случаем?
Цитата Сообщение от DarkMasterW Посмотреть сообщение
^(\\[TEMPLATE.*\\])(\\n)((.|\\n)*?)(item=)(i_gold) - крашит.
^(\\[TEMPLATE.*\\])(\\n)((.|\\n)*?)(item=)(i_) - шуршит.
Этот кусок так же в целом вписывается. Строки (item=)(i_) встречаются через одну, (item=)(i_gold) может и раз через двадцать могут быть. Правда от \\[TEMPLATE.*\\] она всегда находится в 0-2 строках, что несколько озадачивает.
Renji
1535 / 983 / 241
Регистрация: 05.06.2014
Сообщений: 2,967
17.07.2014, 13:43     Regex_replace краши #9
Где посмотреть?
Там где ты стек вызовов нашел. Он должен прокручиваться также как любой другой список. Если, конечно, там есть что прокручивать.
Обрезал до:
Тогда последний тест - поставить boost и использовать его вместо std::regex (синтаксис практически тот же, только с заменой std:: на boost:: ). Если после этого программа внезапно перестанет падать, значит глюк точно в реализации std. C++11 вроде как еще в стадии финальных доработок напильником, так что в реализации действительно может быть косяк.
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
17.07.2014, 20:11  [ТС]     Regex_replace краши #10
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <ctime>
 
#include <regex>
#include <string>
 
#include <fstream>
#include <iomanip>
 
#include <vector>
 
#include <boost/regex.hpp>
 
using namespace std;
 
int main()
{
    setlocale(LC_ALL, "RUS");
 
 
    string inputTextStr; // строка
 
    ifstream inputTextFile; inputTextFile.open("I:\\Downloads\\RegExp\\inputText.txt", ios::binary);
    if (inputTextFile.good())
    {
        inputTextFile.seekg(0, ios::end);
        inputTextStr.resize(inputTextFile.tellg());
        inputTextFile.seekg(0, ios::beg);
 
        inputTextFile.read((char*)inputTextStr.data(), inputTextStr.size());
        inputTextFile.close();
    }
 
    cout << "1:\n";
    string str1 = "\n(\\[TEMPLATE.*\\].*)(\\n)((.|\\n)*?)(item=)(i_gold,)";
    string str2 = "%%%%% %%%%%";
    boost::regex rgExRule(str1, std::tr1::regex_constants::icase);
    inputTextStr = boost::regex_replace(inputTextStr, rgExRule, str2);
    cout << inputTextStr;
    cin.get();
}
1>------ Сборка начата: проект: Tmp, Конфигурация: Debug Win32 ------
1>LINK : fatal error LNK1104: не удается открыть файл "libboost_regex-vc120-mt-gd-1_55.lib"

Regex_replace краши

include не подчеркивает, позволяет открыть boost/regex.hpp через ПКМ. Видимо все-таки видит...

Добавлено через 1 час 15 минут
Не ту папку с либами буста указал. Надо было lib64-msvc-12.0.

Буст тоже крашит... Вот стек вызовов. Что с ним не так не понимаю. Регексп вроде нормальный... По крайней мере в RegEx Coach на ура съедается...

Regex_replace краши

Через STD словил новую радость:
Unhandled exception at 0x000007FEFDC3940D in Tmp.exe: Microsoft C++ exception: std::regex_error at memory location 0x00000000000DBB40.
if (0 < _Max_complexity_count && --_Max_complexity_count <= 0)
_Xregex_error(regex_constants::error_complexity);
внутри regex
DiffEreD
 Аватар для DiffEreD
1420 / 757 / 95
Регистрация: 21.06.2011
Сообщений: 1,740
Записей в блоге: 2
17.07.2014, 23:00     Regex_replace краши #11
Сообщение было отмечено автором темы, экспертом или модератором как ответ
В boost еще есть replace_regex и replace_all_regex. Ваша регулярка у меня работает, никаких проблем не вижу. Компилятор g++ 4.8
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
#include <string>
#include <boost/algorithm/string/regex.hpp>
 
int main()
{
   std::string Input1 =
         "[teMPLATExxxxfdsdg]\n"
         "\n"
         "first\n"
         "second\n"
         "third\n"
         "item=i_gold";
 
   std::string Input2 =
         "[teMPLATExxxxfdsdg]\n"
         "\n"
         "first\n"
         "second\n"
         "third\n"
         "itNOTem=i_gold";
 
   std::string replace = "%%%%% %%%%%";
   boost::regex reg(R"(\[TEMPLATE.*\](\n)((.|\n)*?)(item=i_gold))", boost::regex::icase);
   boost::replace_all_regex(Input1, reg, replace);
   boost::replace_all_regex(Input2, reg, replace);
 
   std::cout << Input1 << "\n\n";
   std::cout << Input2 << "\n\n";
 
   return 0;
}
DarkMasterW
4 / 4 / 0
Регистрация: 25.10.2013
Сообщений: 227
18.07.2014, 10:56  [ТС]     Regex_replace краши #12
inputText очень маленький. Оно и у меня на таком крашить не будет. Хотя бы 1000 строк сделай.

boost::replace_all_regex - так же краш.
boost::replace_regex - выполнил. Я подозревал, что по 1 он выполнять будет... Что-то где-то забивается от объема. А можно вернуть указатель на начало/конец реплейса? Уже думаю велосипед изобретать с единичными вызовами...

C++
1
2
3
4
    for (int b = 0; b < 225; b++){
        boost::replace_regex(inputTextStr, rgExRule, str2);
        cout << b << "\n";
    }
строк для замены 223. Все исправно заменяет. На последней итерации, когда уже строк совпадающих нет вылетает краш... Но я то откуда знаю сколько строк будет на совпадения?

Добавлено через 9 минут
Отбой радости. Урезанный регексп был после экспериментов. Все так же крашит... Причем на 1 же проходе. В урезанном состоянии отрезал хвост файла:
Кликните здесь для просмотра всего текста
ITEM=random_art_high,R500




















[EoF]
и краша на последнем проходе не стало. Вот только то, что нужно так и не работает и не понятно почему...

Добавлено через 11 часов 19 минут
С бустом все завелось и нормально работает. Флаг изначально не поменял std'шный на boost::regex::icase.
Всем большое спасибо за помощь.
Yandex
Объявления
18.07.2014, 10:56     Regex_replace краши
Ответ Создать тему
Опции темы

Текущее время: 16:25. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru