当前位置: 首页 > 知识库问答 >
问题:

导致堆栈溢出的正则表达式

严升
2023-03-14
void Load( const std::string& szFileName )
{
     static const std::regex regexObject( "=== ([^=]+) ===\\n((?:.|\\n)*)\\n=== END \\1 ===", std::regex_constants::ECMAScript | std::regex_constants::optimize );
     static const std::regex regexData( "<([^>]+)>:([^<]*)\\n", std::regex_constants::ECMAScript | std::regex_constants::optimize );

     std::ifstream inFile( szFileName );
     inFile.exceptions( std::ifstream::badbit );

     std::string szFileData( (std::istreambuf_iterator<char>(inFile)), (std::istreambuf_iterator<char>()) );

     inFile.close();

     std::vector<std::future<void>> vecFutures;

     for( std::sregex_iterator itObject( szFileData.cbegin(), szFileData.cend(), regexObject ), end; itObject != end; ++itObject )
     {
          if( (*itObject)[1] == "OBJECT1" )
          {
               vecFutures.emplace_back( std::async( []( std::string szDataString ) {
                    for( std::sregex_iterator itData( szDataString.cbegin(), szDataString.cend(), regexData ) { // Do Stuff }
               }, (*itObject)[2].str() ) );
          }
          else if( (*itObject)[1] == "OBJECT2" )
          {
               vecFutures.emplace_back( std::async( []( std::string szDataString ) {
                    for( std::sregex_iterator itData( szDataString.cbegin(), szDataString.cend(), regexData ) { // Do Stuff }
               }, (*itObject)[2].str() ) );
          }
     }

     for( auto& future : vecFutures )
     {
          future.get();
     }
}
=== OBJECT2 ===
<Name>:Test Manufacturer
<Supplier>:Test Supplier
<Address>:Test Multiline
Contact
Address
<Email>:test@test.co.uk
<Telephone Number>:0123456789
=== END OBJECT2 ===
=== OBJECT1 ===
<Number>:1
<Name>:Test
<Location>:Here
<Manufacturer>:
<Model Number>:12345
<Serial Number>:54321
<Owner>:Me
<IP Address>:0.0.0.0
=== END OBJECT1 ===

我找不到堆栈溢出的来源,但似乎是外部的std::sregex_iterator循环造成的。

提前道谢!

共有1个答案

汤修贤
2023-03-14

下面是另一个尝试:

=== ([^=]+) ===\n((?:(?!===)[^\n]+\n)+)=== END \1 ===

在C++中,它显然可以写成:

=== ([^=]+) ===\\n((?:(?!===)[^\\n]+\\n)+)=== END \\1 ===

这是为了最小的回溯(至少在匹配的时候),虽然我现在有点累脸先生,所以可能错过了相当多的方法来改善它。

它做了两个假设,用来避免大量的回溯(可能导致堆栈溢出,如其他人所说):

  1. 行的开始处没有===,除了开始/结束标记行。
  2. C++支持这些regex特性--特别是使用否定前瞻(?!)。考虑到它是ECMAScript方言,

解释说:

=== ([^=]+) ===\n
((?:
   (?!===)
   [^\n]+\n
)+)
=== END \1 ===

比较(使用RegexBuddy):

原始版本:

  • 第一次匹配:1277步
  • 匹配失败:1步(这是由于对象之间的换行)
  • 第二次匹配:396步
    null
 类似资料:
  • 我正在将一些较旧的Boost regex代码转换为C++11的过程中,我在一个测试用例中偶然发现了一个问题。下面是一个使用std::regex导致堆栈溢出异常的场景,但使用boost::regex可以很好地工作。我没有更改正则表达式模式,并且已经验证了该模式是我想要的。似乎是这个特定的字符串输入片段导致了堆栈溢出。使用VS2012,x64调试生成:

  • 问题内容: 这有效:http : //play.golang.org/p/-Kv3xAguDR。 这导致堆栈溢出:http : //play.golang.org/p/1-AsHFj51O。 我不明白为什么。在这种情况下,使用接口的正确方法是什么? 问题答案: 这个 将呼叫您的,依次呼叫,等等。如果您需要解组JSON然后对其进行处理,那么一种巧妙的技术是声明一个本地类型,将数据解组到其中,然后转换

  • 问题内容: 该类的标准实现使用递归来实现多种形式的正则表达式(例如,某些运算符,替换)。 这种方法会导致输入字符串超过(相对较小)长度(可能不超过1,000个字符)的堆栈溢出问题,具体取决于所涉及的正则表达式。 一个典型的例子是以下正则表达式,它使用交替从周围的XML字符串中提取可能的多行元素(名为),该元素已经提供了: 上面的正则表达式与该方法一起使用,以读取“数据”捕获组并按预期工作,直到提供

  • 我正在使用一个正则表达式从任意长的输入字符串中提取键值对,并且遇到了这样的情况:对于具有重复模式的长字符串,它会导致堆栈溢出。 KV解析代码如下所示: 一些虚构的输出示例: 我显式地将generic放在上面,而不是在解析之前检查最大字符串长度的hacks(例如)。 我能想出的最粗俗的解决方法,一个真正的反模式,是 有趣的是,它在我试过的几次运行中都起作用了,但它不是一个值得推荐的有品位的东西。:-

  • 问题内容: TL; DR: 将任何非内置函数添加到Array.prototype AND Function.prototype将导致IE8本机JSON解析器在解析包含数组的任何JSON时发生堆栈溢出,但仅当您还传递了reviver函数时放入JSON.parse()。 最初这是一个问题,但我回答了我自己的原始问题,所以现在我要问:有人能想到此IE8错误的解决方法,该方法不涉及消除所有修改Array.