【问题标题】:a simple C++11 regex that throws regex_error while searching一个简单的 C++11 正则表达式,在搜索时抛出 regex_error
【发布时间】:2017-08-12 02:04:20
【问题描述】:

我正在使用 VS2015 社区,为什么下面的代码在我的计算机上以特定长度的字符串抛出 std::regex_error

#include <string>
#include <regex>
#include <iostream>

int main()
{
    try {
        std::string subject(497, '-');
        std::regex  pattern("(.)+");
        bool match = std::regex_search(subject, pattern);
        std::cout << std::boolalpha << match << std::endl;
    }
    catch(const std::regex_error& e) {
        std::cerr << "1: " << e.what() << std::endl;
    }

    try {
        std::string subject(498, '-');
        std::regex  pattern("(.)+");
        bool match = std::regex_search(subject, pattern);
        std::cout << std::boolalpha << match << std::endl;
    }
    catch(const std::regex_error& e) {
        std::cerr << "2: " << e.what() << std::endl;
    }
}

输出是:

true
2: regex_error(error_stack): There was insufficient memory to determine whether the regular expression could match the specified character sequence.

谢谢。

【问题讨论】:

  • 也许你的正则表达式太模棱两可了。你应该尝试使用"[-]+"
  • @LingboTang 括号中的单个破折号是什么意思?
  • 这意味着你应该只捕获字符"-"
  • @alfC 这是真的。在此之前,我不知道 regex_search 会抛出异常。谢谢
  • @LingboTang 这不是我想要的。默认情况下,std::regex 使用 ECMAScript 语法,我想匹配包含任何字符的字符串(包括 \r)但 \n\n 分隔的主题中,所以我这样写:((.|\r)*)\n,然后它会崩溃,但不是每次都崩溃。

标签: regex c++11


【解决方案1】:

即使在那里使用集群组(?:.)+ 也会导致error_stack

如果您愿意,我可以告诉您如何减少此异常。
我也可以告诉你是什么原因造成的。

使用regex.h作为参考..

首先,您会注意到这些定义靠近顶部

#ifndef _REGEX_MAX_COMPLEXITY_COUNT
  #define _REGEX_MAX_COMPLEXITY_COUNT   10000000L   /* set to 0 to disable */
 #endif /* _REGEX_MAX_COMPLEXITY_COUNT */


#ifndef _REGEX_MAX_STACK_COUNT
  #ifdef _WIN64
   #define _REGEX_MAX_STACK_COUNT   600L    /* set to 0 to disable */
  #else /* _WIN64 */
   #define _REGEX_MAX_STACK_COUNT   1000L   /* set to 0 to disable */
  #endif /* _WIN64 */
#endif /* _REGEX_MAX_STACK_COUNT */

要禁用复杂性或最大堆栈,请在编译时放置定义
你想要之前包含文件&lt;regex&gt;

例如,设置为 0 可禁用这些保护。
对于您的测试,我们可以像这样将堆栈设置为 200,000

#define _REGEX_MAX_STACK_COUNT 200000
#include <regex>

对于您的示例,现在实际上不会引发异常。

第二,代码中出现这种情况的原因。

我只是看了一眼调试会话,发现了一般原因。

这一切都来自 _Matcher 类。

_Match_pat() 内,它首先递减 _Max_stack_count,
在退出之前增量 _Max_stack_count。

_Max_stack_count 在 _Matcher 被实例化时被设置。

模板类_Matcher
{ // 提供将正则表达式匹配到文本序列的方法

  _Max_stack_count = _REGEX_MAX_STACK_COUNT;

}

递归来自_Match_pat()被递归调用
_Do_if()_Do_rep()最初从_Match_pat()调用

并且行为主要来自开放式量化组(捕获或聚类),可以匹配很多次。

在你的情况下,它的(.)+
不同寻常的是,所有这些都是匹配一个字符并将其放入
在捕获组 1 中,但将其附加到组 0。

在我看来,闭包应该记录可用堆栈计数的增量
(pop),但递归被用作支持
其他国家必须重复考虑这一点。

无论如何,您可以设置断点并自己尝试一下。

以下是感兴趣的代码段。

    bool _Matcher<>::_Match_pat(_Node_base *_Nx)
    {
        if (0 < _Max_stack_count && --_Max_stack_count <= 0)
            _Xregex_error(regex_constants::error_stack);
        while (_Nx != 0)
        {

            case _N_if:
                if (!_Do_if((_Node_if *)_Nx))
                    _Failed = true;
                _Nx = 0;
                break;

            case _N_endif:
                break;

            case _N_rep:
                if (!_Do_rep((_Node_rep *)_Nx,
                    (_Nx->_Flags & _Fl_greedy) != 0, 0))
                    _Failed = true;
                _Nx = 0;
                break;

            case _N_end_rep:
                {   // return at end of loop
                _Node_rep *_Nr = ((_Node_end_rep *)_Nx)->_Begin_rep;
                _Loop_vals_t *_Psav = &_Loop_vals[_Nr->_Loop_number];

                if (_Nr->_Simple_loop == 0 && !_Do_rep(_Nr,
                    (_Nr->_Flags & _Fl_greedy) != 0, _Psav->_Loop_idx))
                    _Failed = true; // recurse only if loop contains if/do
                _Nx = 0;
                break;
                }


        }
        if (0 < _Max_stack_count)
        ++_Max_stack_count;
    }


    bool _Matcher<>::_Do_rep0()
    {   // apply repetition to loop with no nested if/do

        if (!_Match_pat(_Node->_Next))      // Several of these
    }

    bool _Matcher<>::_Do_if()
    {   // apply if node
        if (_Match_pat(_Node->_Next)) // try to match this branch
    }    

【讨论】:

  • 非常感谢。有时候,我只是对 c++ 有点生气。
  • @user3628322 - 是的,这很难。请注意,您可以将_REGEX_MAX_STACK_COUNT=&lt;number&gt; 放入您的项目定义中。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-03
  • 2010-12-05
  • 1970-01-01
  • 2016-09-17
  • 2011-12-19
  • 1970-01-01
相关资源
最近更新 更多