一个数字的提升精神解析器的分段错误

Segmentation fault with boost spirit parser for one digit

我正在尝试使用 Boost.Spirit。 当我测试一个非常简单的解析器时,它只能解析一个数字,程序崩溃了。

#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

auto const noneZero = qi::char_('1') |
                      qi::char_('2') |
                      qi::char_('3');

int main(int argc, char** argv)
{
    std::string input = "9";
    std::string output;

    if (qi::parse(input.begin(), input.end(), noneZero, output))
    {
        std::cout << "Ok => '" << output << "'\n";
    }
    else
    {
        std::cout << "No\n";
    }
    return 0;
}

我做错了什么? 应该是一个很简单的案例,我想不出我哪里做错了。

陌生人,如果我写下面的代码一切正常... 但为什么?!语法应该是一样的吧?

#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

auto const noneZero = qi::char_('1', '9');

int main(int argc, char** argv)
{
    std::string input = "9";
    std::string output;

    if (qi::parse(input.begin(), input.end(), noneZero, output))
    {
        std::cout << "Ok => '" << output << "'\n";
    }
    else
    {
        std::cout << "No\n";
    }
    return 0;
}

更有趣的是,下面的程序没有崩溃:

#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

auto const noneZero = qi::char_('1') |
                      qi::char_('2');

int main(int argc, char** argv)
{
    std::string input = "9";
    std::string output;

    if (qi::parse(input.begin(), input.end(), noneZero, output))
    {
        std::cout << "Ok => '" << output << "'\n";
    }
    else
    {
        std::cout << "No\n";
    }
    return 0;
}

有人可以解释为什么这个语法不会崩溃:

auto const noneZero = qi::char_('1') |
                      qi::char_('2');

为什么这个语法崩溃:

auto const noneZero = qi::char_('1') |
                      qi::char_('2') |
                      qi::char_('3');

怀疑我自己的电脑有问题,我在coliru上试了所有这些例子,结果都是一样的。 所有这些示例都是使用以下命令编译的:

clang++ test.cpp -Wall -Werror -Wextra --std=c++14

您正在使用 auto,但没有深度复制 Proto 表达式树。这会创建悬挂引用,因此 Undefined Behaviour.

这是一个修复方法(也请注意更短的书写方式):

auto const nonZero = qi::copy(qi::char_("1-3"));

你也可以只写

auto const nonZero = qi::copy(qi::digit - '0');

所有其他示例 "working" 仍然是未定义行为 (UB)。如果你越界,任何事情都可能发生。

现场演示

Live On Coliru

#include <boost/spirit/include/qi.hpp>
#include <iostream>
#include <string>

namespace qi = boost::spirit::qi;

auto const nonZero = qi::copy(qi::char_("1-9"));

int main(int argc, char** argv)
{
    std::string input = "9";
    std::string output;

    if (qi::parse(input.begin(), input.end(), nonZero, output))
    {
        std::cout << "Ok => '" << output << "'\n";
    }
    else
    {
        std::cout << "No\n";
    }
    return 0;
}

版画

Ok => '9'