【问题标题】:Why did boost regex run out of stack space?为什么 boost regex 会耗尽堆栈空间?
【发布时间】:2011-05-28 14:24:06
【问题描述】:
#include <boost/regex.hpp>
#include <string>
#include <iostream>

using namespace boost;
static const regex regexp(
        "std::vector<"
            "(std::map<"
                   "(std::pair<((\\w+)(::)?)+, (\\w+)>,?)+"
             ">,?)+"
        ">");

std::string errorMsg =
"std::vector<"
        "std::map<"
                "std::pair<Test::Test, int>,"
                "std::pair<Test::Test, int>,"
                "std::pair<Test::Test, int>"
        ">,"
        "std::map<"
                "std::pair<Test::Test, int>,"
                "std::pair<Test::Test, int>,"
                "std::pair<Test::Test, int>"
        ">"
">";
int main()
{
    smatch result;
    if(regex_match(errorMsg, result, regexp))
    {  
        for (unsigned i = 0; i < result.size(); ++i)
        {  
            std::cout << result[i] << std::endl;
        }
    }

//    std::cout << errorMsg << std::endl;

    return 0;
}

这会产生:

terminate called after throwing an instance of 'boost::exception_detail::clone_impl<boost::exception_detail::error_info_injector<std::runtime_error>
>'   what():  Ran out of stack space trying to match the regular expression.

编译

g++ regex.cc -lboost_regex

编辑

我的平台:

g++ (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5
libboost-regex1.42
Intel(R) Core(TM)2 Quad CPU Q9400 @ 2.66GHz
So the latest Ubuntu 64 bit

【问题讨论】:

    标签: c++ regex boost boost-regex


    【解决方案1】:

    ((\\w+)(::)?)+ 是所谓的“病态”正则表达式之一——它需要指数级的时间,因为你有两个相互依赖的表达式,一个接一个。也就是说,由于catastrophic backtracking而失败。

    考虑我们是否遵循链接的示例,并将“更复杂的东西”简化为“x”。让我们用\\w 来做吧:

    • ((x+)(::)?)+

    我们还假设我们的输入永远不会有::。这样做实际上会使正则表达式更加复杂,所以如果我们排除复杂性,那么我们真的应该让事情变得更简单:

    • (x+)+

    现在你有一个像上面链接中详述的教科书嵌套量词问题。

    有几种方法可以解决这个问题,但最简单的方法可能是使用 atomic group modifier "(?&gt;" 来禁止内部匹配的回溯:

    • ((?&gt;\\w+)(::)?)+

    【讨论】:

    • 一个病态的子正则表达式可能是问题所在,但这不是你提到的那个——\w 只是[A-Za-z0-9_] 或附近,所以它已经排除了,: 只是就像您提出的修复一样,因此需要相同的时间。此外,我认为您需要在两个正则表达式上都有一个开放的括号。
    • @j_random_hacker:嗯..好点。我提出的修复方法并没有解决问题,但灾难性的回溯是问题所在……给我一点时间来修复它。
    • 你能重现这个问题吗?
    • @nice: std::vector&lt;(std::map&lt;(std::pair&lt;((?&gt;\w+)(::)?)+, (\w+)&gt;,?)+&gt;,?)+&gt; 为我工作。 (虽然我使用 RegexBuddy 进行测试而不是 Boost)
    • @nice:很公平,但是如果执行任何回溯,打开该功能几乎肯定会破坏堆栈,所以我建议不要这样做。
    【解决方案2】:

    在本地测试过,效果很好,我猜你的编译器做了一些奇怪的事情。

    什么版本的gcc?什么平台?哪个版本的 boost?

     -> ./regex
    std::vector<std::map<std::pair<Test::Test, int>,std::pair<Test::Test, int>,std::pair<Test::Test, int>>,std::map<std::pair<Test::Test, int>,std::pair<Test::Test, int>,std::pair<Test::Test, int>>>
    std::map<std::pair<Test::Test, int>,std::pair<Test::Test, int>,std::pair<Test::Test, int>>
    std::pair<Test::Test, int>
    Test
    Test
    ::
    int
    

    【讨论】:

    • 我的测试是使用boost-1.42 / gcc version 4.5.1 (Gentoo 4.5.1-r1 p1.4, pie-0.4.5),是否可以尝试不同版本的 gcc 和/或 boost?
    • 奇怪。我可以在其他地方尝试,但稍后。我会看到我对其他版本的能力
    • 仅供参考,我正在访问这个网页,因为在旧版本的 boost (1.43.0) 下工作的代码在新版本的 boost (1.53.0) 上遇到了这个堆栈空间错误。因此,boost 的版本似乎与问题是否出现有关。
    猜你喜欢
    • 1970-01-01
    • 2014-02-10
    • 2012-06-30
    • 2020-01-20
    • 2017-09-16
    • 2012-04-09
    • 1970-01-01
    • 2012-03-08
    • 1970-01-01
    相关资源
    最近更新 更多