为什么这个正则表达式“冻结”VC ++中的程序?

时间:2018-05-08 17:38:30

标签: c++ regex visual-c++

我有以下代码,最初是使用C ++ 11的正则表达式库(#include <regex>)编写的,但现在使用Boost尝试进行故障排除:

boost::regex reg(R"(.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)))", boost::regex::icase);
boost::cmatch matches;

if (boost::regex_match(request, reg) && matches.size() > 1)
{
    printf("Match found");
}
else
{
    printf("No match.");
}

执行时,此代码似乎在boost::regex_match(request, reg)上“冻结”,好像需要很长时间才能处理。我等了五分钟才能处理(如果是处理问题),但程序状态是一样的。

tested the STL's regex library version of the above code online on cpp.sh and onlinegdb,它在那里完美无瑕。然后我将此代码复制到VC ++项目中,代码再次冻结:

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

int main()
{
    std::string request = "\\login\\\\challenge\\jRJkdflp3gvTzrwiQ3tyKSqnyppmaZog\\uniquenick\\Lament\\partnerid\\0\\response\\4767846ef255a88da9b10f7c923a1e6e\\port\\-14798\\productid\\11489\\gamename\\crysiswars\\namespaceid\\56\\sdkrevision\\3\\id\\1\\final\\";
    std::regex reg(R"(.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)))", std::regex::icase);
    std::smatch matches;

    if (std::regex_search(request, matches, reg) && matches.size() > 1)
    {
        printf("Match found");
    }
    else
    {
        printf("No match.");
    }
}

相关字符串如下:

  

\登录\挑战\ jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog \ uniquenick \用户\ PARTNERID \ 0 \响应\ 4767846ef255a83da9b10f7f923a1e6e \端口14798 \的productid \ 11489 \ gamename \ crysiswars \名称空间ID \ 56 \ sdkrevision \ 3 \ ID \ 1 \最终\

我在另一台计算机(全新项目)上的Visual Studio 2017安装上测试了相同的代码并得到完全相同的结果......这似乎表明编译器正在做的事情导致代码冻结/采取很长一段时间的处理。我目前无法在本地测试另一个编译器。

正则表达式字符串checks out on regex101,所以功能表达式正常。

这是针对v141的Visual Studio 2017 Professional。

为什么会发生这种情况,我该如何解决?

1 个答案:

答案 0 :(得分:2)

你的问题是回溯问题 在 boost 示例中,您使用强制匹配的regex_match 整串。
如果使用regex_search并添加^..$,您将获得相同的结果。

然而,你的字符串永远不能匹配,因为你已经强制它结束了 在一封信上,但字符串真的以反斜杠结尾 这会强制引擎重试所有.*?个位置。

修复方法是在正则表达式的末尾放置一个最终.*?,这样就可以了 正则表达式实现了匹配整个字符串的使命。

其他事情可能有所帮助,你可以稍微清理你的正则表达式和/或添加一些 原子组和/或添加一些斜杠来代替那些.*?

无论如何,请使用:

^.*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z]*[0-9]+[a-z0-9]*)).*?((?:[a-z][a-z]+)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z0-9_]*)).*?(\d+).*?((?:[a-z][a-z]+)).*?(\d+).*?((?:[a-z][a-z]+)).*?$

输出

 **  Grp 0 -  ( pos 0 : len 207 ) 
\login\challenge\jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog\uniquenick\User\partnerid\0\response\4767846ef255a83da9b10f7f923a1e6e\port-14798\productid\11489\gamename\crysiswars\namespaceid\56\sdkrevision\3\id\1\final\  
 **  Grp 1 -  ( pos 1 : len 5 ) 
login  
 **  Grp 2 -  ( pos 7 : len 9 ) 
challenge  
 **  Grp 3 -  ( pos 17 : len 32 ) 
jRJwdflp3gvTrrwiQ3tyKSqnyppmaZog  
 **  Grp 4 -  ( pos 50 : len 10 ) 
uniquenick  
 **  Grp 5 -  ( pos 61 : len 4 ) 
User  
 **  Grp 6 -  ( pos 66 : len 9 ) 
partnerid  
 **  Grp 7 -  ( pos 76 : len 1 ) 
0  
 **  Grp 8 -  ( pos 78 : len 8 ) 
response  
 **  Grp 9 -  ( pos 94 : len 25 ) 
ef255a83da9b10f7f923a1e6e  
 **  Grp 10 -  ( pos 120 : len 4 ) 
port  
 **  Grp 11 -  ( pos 125 : len 5 ) 
14798  
 **  Grp 12 -  ( pos 131 : len 9 ) 
productid  
 **  Grp 13 -  ( pos 141 : len 5 ) 
11489  
 **  Grp 14 -  ( pos 147 : len 8 ) 
gamename  
 **  Grp 15 -  ( pos 156 : len 10 ) 
crysiswars  
 **  Grp 16 -  ( pos 167 : len 11 ) 
namespaceid  
 **  Grp 17 -  ( pos 179 : len 2 ) 
56  
 **  Grp 18 -  ( pos 182 : len 11 ) 
sdkrevision  
 **  Grp 19 -  ( pos 194 : len 1 ) 
3  
 **  Grp 20 -  ( pos 196 : len 2 ) 
id  
 **  Grp 21 -  ( pos 199 : len 1 ) 
1  
 **  Grp 22 -  ( pos 201 : len 5 ) 
final