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

标签 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;

对于(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。

'好吧,让我们试试 clang,它很流行,旨在取代 gcc'——我从来没有这么错。使用 -O0 clang (v. 3.7.1) 在 9696 个空间上崩溃 - 少于 gcc,但不多,但使用 -O3 甚至使用 -O2 它在零个空格处崩溃。

故障转储显示大量堆栈跟踪(35k 帧)的递归调用

std::__detail::_Executor<char*, std::allocator<std::__cxx11::sub_match<char*> >, std::__cxx11::regex_traits<char>, true>::_M_dfs

问题 1:这是一个错误吗?如果是,我应该举报吗?

问题 2:有没有聪明的方法来解决这个问题(除了增加系统堆栈大小、尝试其他正则表达式库和编写自己的函数来替换空格)?


修正: bug report为 libstdc++ 创建

最佳答案

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

是的,这是一个错误。

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

这已在 libstdc++ here 中出现错误.

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

如果你要求一个新的 regex 可以工作,我已经尝试了几个不同的版本,但它们都在 libstdc++ 上失败了,所以我想说,如果你想使用 regex 来解决这个问题,您需要针对 libc++ 进行编译。

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

更好的解决方案可以使用 adjacent_find其中runs fine with libstdc++ as well :

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); }));
}

这将返回与您的 regex 相同的内容:

"Small text with several lines. "

但如果您为了简单起见,也可以使用 unique :

test.resize(distance(test.begin(), unique(test.begin(), test.end(), [](const auto& a, const auto& b) { return isspace(a) && isspace(b); })));

哪个会返回:

"Small text
with several
lines. "

关于长序列上的 C++ 正则表达式段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36304204/

相关文章:

C++ 数组排序

c++ - 我怎样才能让我的 viewcontroller 成为 C++ 书面主题的观察者

php - 切割 HTML 标签并重新包装 HTML 标签 Part/1

java - 如何使用正则表达式java从字符串中提取第一个字母和后面的三个数字

c++ - 在没有 std::stod 的情况下从 vector<string> 转换为 vector<double>

c - gcc makefile 带有 -Wall -pedantic 和 -lpthread

c++ - ifstream eof 循环读入条件表达式中的变量?

c++ - 从同一网络中另一台机器的哈希表获取 wordID

regex - 我如何配置 Jenkins 来构建除我排除的少数分支之外的所有分支?

c可以声明两个具有相同名称,返回类型但参数不同的函数吗