gpt4 book ai didi

c++ - 在boost::qi中使用太多替代运算符导致段错误

转载 作者:行者123 更新时间:2023-12-01 14:57:25 24 4
gpt4 key购买 nike

我使用qi::spirit生成了一个简单的代码:

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

using namespace std;
using namespace boost::spirit;
int main() {
string str = "string";
auto begin = str.begin();
auto symbols = (qi::lit(";") | qi::lit("(") | qi::lit(")") | qi::lit("+") |
qi::lit("/") | qi::lit("-") | qi::lit("*"));
qi::parse(begin, str.end(), *(qi::char_ - symbols));
}
然后SEGV终止了该程序。
我用较少的符号rhs替代运算符重写代码,
#include <boost/spirit/include/qi.hpp>
#include <string>
using namespace std;
using namespace boost::spirit;
int main()
{
string str = "string";
auto begin = str.begin();
auto symbols = (qi::lit(";") | qi::lit("+") | qi::lit("/") | qi::lit("-") |
qi::lit("*"));
qi::parse(begin, str.end(), *(qi::char_ - symbols));
}
现在运作良好。 2种情况有什么区别?

最佳答案

您的问题是一个经典错误:使用auto存储Qi解析器表达式:Assigning parsers to auto variables
这导致UB

  • 使用规则或qi::copy(即已托管的proto::deep_copy)。
    auto symbols = qi::copy(qi::lit(";") | qi::lit("(") | qi::lit(")") | qi::lit("+") |
    qi::lit("/") | qi::lit("-") | qi::lit("*"));
  • 更妙的是,使用字符集一次匹配所有字符,
    auto symbols = qi::copy(qi::omit(qi::char_(";()+/*-")));
    omit[]抵消了char_公开其属性的事实(而lit没有)。但是既然您所要做的就是从另一个字符集中减去:
    qi::char_ - symbols
    你也可以写
    qi::char_ - qi::char_(";()+/*-")
    现在。您可能不知道,但是您可以使用~charset对其进行否定,因此它将变成
    ~qi::char_(";()+/*-")

    NOTE - can have special meaning in charsets, which is why I very subtly move it to the end. See docs



  • 现场演示
    扩展一点并显示一些更巧妙的模式:
    Live On Coliru
    #include <boost/spirit/include/qi.hpp>
    #include <iomanip>
    #include <string>

    using namespace std;
    using namespace boost::spirit;
    int main() {
    string const str = "string;some(thing) else + http://me@host:*/path-element.php";

    auto cs = ";()+/*-";
    using qi::char_;

    {
    std::vector<std::string> tokens;
    qi::parse(str.begin(), str.end(), +~char_(cs) % +char_(cs), tokens);

    std::cout << "Condensing: ";
    for (auto& tok : tokens) {
    std::cout << " " << std::quoted(tok);
    }
    std::cout << std::endl;
    }

    {
    std::vector<std::string> tokens;
    qi::parse(str.begin(), str.end(), *~char_(cs) % char_(cs), tokens);

    std::cout << "Not condensing: ";
    for (auto& tok : tokens) {
    std::cout << " " << std::quoted(tok);
    }
    std::cout << std::endl;
    }
    }
    版画
    Condensing:  "string" "some" "thing" " else " " http:" "me@host:" "path" "element.php"
    Not condensing: "string" "some" "thing" " else " " http:" "" "me@host:" "" "path" "element.php"
    X3
    如果您使用的是c++ 14,则可以使用没有“自动问题”的Spirit X3(因为它没有可以悬挂引用的Proto Expression树)。
    您的原始代码 would have been fine in X3,它将更快地编译。
    这是我使用X3的示例:
    Live On Coliru
    #include <boost/spirit/home/x3.hpp>
    #include <iostream>
    #include <iomanip>
    #include <string>

    namespace x3 = boost::spirit::x3;
    int main() {
    std::string const str = "string;some(thing) else + http://me@host:*/path-element.php";
    auto const cs = x3::char_(";()+/*-");

    std::vector<std::string> tokens;
    x3::parse(str.begin(), str.end(), +~cs % +cs, tokens);
    //x3::parse(str.begin(), str.end(), *~cs % cs, tokens);

    for (auto& tok : tokens) {
    std::cout << " " << std::quoted(tok);
    }
    }
    列印
     "string" "some" "thing" " else " " http:" "me@host:" "path" "element.php"

    关于c++ - 在boost::qi中使用太多替代运算符导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62502899/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com