Я анализировал свалку stackoverflow и придумал этот, казалось бы, невинный вопрос с небольшими, почти невидимыми деталями, которые имеют 22311 пробелов в конце текста.
Я использую std:: regex (как-то они работают лучше для меня, чем boost:: regex), чтобы заменить все непрерывные пробелы одним пространством следующим образом:
std::regex space_regex("\\s+", std::regex::optimize);
...
std::regex_replace(out, in, in + strlen(in), space_regex, " ");
SIGSEGV появляется, и я начал исследовать.
Тестовый код:
#include <regex>
...
std::regex r("\\s+", std::regex::optimize);
const char* bomb2 = "Small text\n\nwith several\n\nlines.";
std::string test(bomb2);
for (auto i = 0; i < N; ++i) test += " ";
std::string out = std::regex_replace(test.c_str(), r, " ");
std::cout << out << std::endl;
для (gcc 5.3.0)
$ g++ -O3 -std=c++14 regex-test.cpp -o regex-test.out
максимум N
до появления SIGSEGV - 21818 (для этой конкретной строки) и для
$ g++ -O0 -std=c++14 regex-test.cpp -o regex-test.out
it 12180.
'Хорошо, пусть попробует clang, это тренда и нацелено на замену gcc' - никогда не было так плохо. С -O0
clang (v. 3.7.1) падает на 9696 пробелов - меньше, чем gcc, но не много, но с -O3
и даже с -O2
он падает в пространствах ZERO.
Дамп сбоя представляет огромные стеки (35k кадров) рекурсивных вызовов
std::__detail::_Executor<char*, std::allocator<std::__cxx11::sub_match<char*> >, std::__cxx11::regex_traits<char>, true>::_M_dfs
Вопрос 1: Это ошибка? Если да, должен ли я сообщить об этом?
Вопрос 2: есть ли умный способ преодолеть проблему (кроме увеличения размера системного стека, попыток других библиотек регулярных выражений и запись собственной функции для замены пробелов)?
Поправка: отчет об ошибке, созданный для libstdС++