我正在使用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.
感谢。
答案 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。
_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
}