长序列上的C ++正则表达式段错误

时间:2016-03-30 09:03:16

标签: c++ regex gcc clang c++14

我正在解析stackoverflow转储并且出现在this看似无辜的问题上,其中有一个小的,几乎看不见的细节,它在文本末尾有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;

for(gcc 5.3.0)

$ g++ -O3 -std=c++14 regex-test.cpp -o regex-test.out
在SIGSEGV显示之前

最大N是21818(对于此特定字符串),对于

$ g++ -O0 -std=c++14 regex-test.cpp -o regex-test.out

这是12180。

'好吧,让我们尝试铿锵,这是趋势,旨在取代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 :是否有智能方法来解决问题(除了增加系统堆栈大小,尝试其他正则表达式库并编写自己的函数来替换空格)?

为libstdc ++创建的

修正案 bug report

2 个答案:

答案 0 :(得分:8)

这是一个错误吗?如果是,我应该报告吗?

是的,这是一个错误。

cout << '"' << regex_replace("Small text\n\nwith several\n\nlines." + string(22311, ' '), regex("\\s+", regex::optimize), " ") << '"' << endl;

但这只是针对libstdc ++的错误,所以请随时在此报告:https://gcc.gnu.org/bugzilla/buglist.cgi?product=gcc&component=libstdc%2B%2B&resolution=---

有没有聪明的方法来解决这个问题?

如果你要求一个有用的新regex,我尝试了一些不同的版本,并且所有这些版本都在libstdc ++上失败了,所以我想说,如果你想使用{ {1}}要解决这个问题,你需要针对libc ++进行编译。

但老实说,如果您使用regex去除重复的空格,"Now you have two problems"

更好的解决方案可以使用adjacent_find

runs fine with libstdc++ as well
regex

这将返回您的const auto func = [](const char a, const char b){ return isspace(a) && isspace(b); }; for(auto it = adjacent_find(begin(test), end(test), func); it != end(test); it = adjacent_find(it, end(test), func)) { *it = ' '; it = test.erase(next(it), find_if_not(next(it), end(test), [](const auto& i) { return isspace(i); })); } 会:

  

“有几行的小文字。”

但如果你想要简单,你也可以使用unique

regex

将返回:

  

“小文字
  有几个   线。 “

答案 1 :(得分:0)

问题2(克服问题的聪明方法)

不是很聪明但是......你可以迭代有限的替代品。

一个例子

#include <regex>
#include <iostream>

int main()
 {
   constexpr int N = 22311;

   //std::regex r("\\s+");
   std::regex r("\\s{2,100}");

   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 = test;

   std::size_t  preSize;

   do
    {
      preSize = out.size();

      out = std::regex_replace(out, r, " ");
    }
   while ( out.size() < preSize );

   std::cout << '\"' << out << '\"' << std::endl;

   return 0;
 }