为什么我的Perl regex使用这么多内存?

时间:2020-03-06 15:03:40  来源:igfitidea点击:

我正在对一个大标量运行一个正则表达式。尽管此匹配项没有捕获任何内容,但此匹配项后,我的过程增长了3000万:

# A
if (${$c} =~ m/\G<<\s*/cgs)
{
    #B
    ...
}

$ c是对相当大的标量(大约21M)的引用,但是我已经验证了pos($ {$ c})在正确的位置,并且表达式在第一个字符与pos匹配。 ($ {$ c})`会在比赛结束后更新到正确的位置。但是正如我所提到的,即使我没有用这个比赛来捕捉任何东西,#A和#B之间的过程也增长了大约30M。我的记忆要去哪里?

编辑:是的,$&的使用是罪魁祸首。我们使用的是Perl 5.8.8,我的脚本使用的是Getopt :: Declare,它使用内置的Text :: Balanced。这个模块的1.95版本使用的是$&。 Perl 5.10附带的2.0.0版本删除了对" $&"的引用,从而缓解了该问题。

解决方案

只是快速的健全性检查,我们在代码中的任何地方都提到$&,$`或者$'(有时称为$ MATCH,$ PREMATCH和$ POSTMATCH)吗?如果是这样,Perl将为每个正则表达式匹配项复制整个字符串,以防万一我们想检查那些变量。

在这种情况下,"在代码中"是间接的,包括使用引用这些变量的模块,或者编写"使用英语"而不是"使用英语qw(-no_match_vars)"。

如果不确定,可以使用Devel :: SawAmpersand模块确定是否已使用它们,并使用Devel :: FindAmpersand确定使用它们的位置。

内存增加可能还有其他原因(我们使用的是哪个版本的Perl?),但是如果使用match变量,肯定会破坏内存,因此可能是罪魁祸首。

谢里奥,

保罗