一个简单的C ++ 11正则表达式,在搜索时抛出regex_error

时间:2017-03-20 17:02:54

标签: regex c++11

我正在使用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.

感谢。

1 个答案:

答案 0 :(得分: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 */

要禁用复杂性或最大堆栈,请在编译时输入定义
之前包含文件<regex>

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

#define _REGEX_MAX_STACK_COUNT 200000
#include <regex>

现在这实际上不会为您的示例抛出异常。

第二,这是代码中的原因。

我只是看了一下调试会话,发现了一个普遍的原因。

这一切都来自_Matcher课程。

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

实例化_Matcher时,

_Max_stack_count被设置。

  

模板&lt;&gt;类_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
    }