提升灵气因记忆违规而崩溃

2024-01-14

但我不明白为什么......?

http://coliru.stacked-crooked.com/a/2912593bb421a35e http://coliru.stacked-crooked.com/a/2912593bb421a35e

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace bsq = boost::spirit::qi;

int main()
{        
    std::uint16_t major, minor, build, revision;

    auto versionParser =
        bsq::uint_
        >> -('.' >> bsq::uint_)
        >> -('.' >> bsq::uint_)
        >> -('.' >> bsq::uint_);

    std::string version = "3.5.1";

    auto start = version.begin();
    if (!bsq::parse(start, version.end(), versionParser, major, minor, build, revision))
    {
        std::cout << "Error!\n";
    }

    std::cout << major << "-" << minor << "-" << build << "-" << revision << std::endl;

    return 0;
}

致电给parse()导致内存访问冲突。

我发誓我曾经有过这个工作,但是……也许我在做白日梦。我已经在 Windows 上使用 Visual Studio 2017 进行了尝试,也在 Coliru 上使用 clang 进行了尝试。我看不到错误。

谢谢。


问题是使用auto表达式来捕获规则,从解析器表达式推导出类型。该类型是一个原始表达式树,它通过引用捕获任何关系,但这意味着许多中间体在封闭的结束后就消失了充分表达 http://eel.is/c++draft/intro.execution#def:full-expression (see C++:临时参数的寿命? https://stackoverflow.com/questions/2506793/c-life-span-of-temporary-arguments).

这是众所周知的,正如您在这里看到的:

  • 将解析器分配给自动变量 https://stackoverflow.com/questions/22023779/assigning-parsers-to-auto-variables/22027181#22027181
  • boost Spirit V2 qi 与优化级别相关的错误 https://stackoverflow.com/questions/20763665/boost-spirit-v2-qi-bug-associated-with-optimization-level/20766909#20766909
  • boost::spirit::qi::phrase_parse 中某处未定义的行为 https://stackoverflow.com/questions/26410498/undefined-behaviour-somewhere-in-boostspiritqiphrase-parse
  • 还有更多

这是最简单的修复:

auto versionParser = bsq::copy(
    bsq::uint_
    >> -('.' >> bsq::uint_)
    >> -('.' >> bsq::uint_)
    >> -('.' >> bsq::uint_));

If you also fix缺少局部变量的初始化它可以正常工作:

Live On Coliru http://coliru.stacked-crooked.com/a/fd704b7026c7fb3e

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/include/qi.hpp>

namespace bsq = boost::spirit::qi;

int main()
{    
    std::cout << "BOOST_VERSION: " << BOOST_VERSION << std::endl;

    std::uint16_t major = 0, minor = 0, build = 0, revision = 0;

    auto versionParser = bsq::copy(
        bsq::uint_
        >> -('.' >> bsq::uint_)
        >> -('.' >> bsq::uint_)
        >> -('.' >> bsq::uint_));

    std::string version = "3.5.1";

    auto start = version.begin();
    if (!bsq::parse(start, version.end(), versionParser, major, minor, build, revision))
    {
        std::cout << "Error!\n";
    }

    std::cout << major << "-" << minor << "-" << build << "-" << revision << std::endl;
}

Prints

BOOST_VERSION: 106600
3-5-1-0

补充笔记

  1. 为了避免整个“统一属性”的情况,让解析器分配给所有元素,即使在输入文本中未指定:

        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
    
  2. 诊断存在尾随“垃圾”的错误(例如"3.4bogus"),您可以添加一个检查来检查完整的输入是否被解析:

    auto versionParser = bsq::copy(
        bsq::uint_
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> bsq::eoi);
    
  3. 因为版本在语义上是一个元组,为什么不这样表示它呢?

    using Version = std::tuple<uint16_t, uint16_t, uint16_t, uint16_t>;
    Version parsed;
    
    if (!bsq::parse(version.begin(), version.end(), versionParser, parsed))
        std::cout << "Error!\n";
    

    这样你甚至可以说:

    using boost::fusion::operator<<;
    
    auto obsolete = parsed < Version(3, 4, 0, 0);
    std::cout << "Version " << parsed << " " << (obsolete? "too old" : "supported") << "\n";
    

结合这些:

Live On Coliru http://coliru.stacked-crooked.com/a/64b16260c559556e

#include <boost/fusion/adapted/std_tuple.hpp>
#include <boost/spirit/include/qi.hpp>

namespace bsq = boost::spirit::qi;

int main() {    
    auto versionParser = bsq::copy(
        bsq::uint_
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> ('.' >> bsq::uint_ | bsq::attr(0))
        >> bsq::eoi);

    std::string version = "3.5.1";

    using Version = std::tuple<uint16_t, uint16_t, uint16_t, uint16_t>;
    Version parsed;

    if (!bsq::parse(version.begin(), version.end(), versionParser, parsed))
        std::cout << "Error!\n";

    using boost::fusion::operator<<;

    auto obsolete = parsed < Version(3, 4, 0, 0);
    std::cout << "Version " << parsed << " " << (obsolete? "too old" : "supported") << "\n";
}

Prints

Version (3 5 1 0) supported

std::tuple sucks?

我同意。因此,等效地编写您自己的结构:

Live On Coliru http://coliru.stacked-crooked.com/a/86b37d7460bd6db1

struct Version {
    uint16_t major, minor, revision, build;

    auto key() const { return std::tie(major, minor, revision, build); }
    bool operator<(Version const& b) const { return key() < b.key(); }
};

BOOST_FUSION_ADAPT_STRUCT(Version, major, minor, revision, build)

与时俱进

请注意,Spirit X3(进入振奋精神;齐还是X3? https://stackoverflow.com/questions/52990661/getting-into-boost-spirit-qi-or-x3/52991170#52991170) 没有auto-您遇到的问题:

Live On Coliru http://coliru.stacked-crooked.com/a/93a33781789224ea

#include <boost/fusion/adapted/struct.hpp>
#include <boost/spirit/home/x3.hpp>

#include <boost/fusion/include/io.hpp>
#include <iostream>

namespace bsx = boost::spirit::x3;

struct Version {
    uint16_t major, minor, revision, build;

    auto key() const { return std::tie(major, minor, revision, build); }
    bool operator<(Version const& b) const { return key() < b.key(); }
};

BOOST_FUSION_ADAPT_STRUCT(Version, major, minor, revision, build)

int main() {    
    auto versionParser = bsx::uint_
        >> ('.' >> bsx::uint_ | bsx::attr(0))
        >> ('.' >> bsx::uint_ | bsx::attr(0))
        >> ('.' >> bsx::uint_ | bsx::attr(0))
        >> bsx::eoi;

    std::string version = "3.5.1";

    Version parsed;

    if (!parse(version.begin(), version.end(), versionParser, parsed))
        std::cout << "Error!\n";

    using boost::fusion::operator<<;

    auto obsolete = parsed < Version{3, 4, 0, 0};
    std::cout << "Version " << parsed << " " << (obsolete? "too old" : "supported") << "\n";
}

打印也一样。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

提升灵气因记忆违规而崩溃 的相关文章

  • 将运算符 << 添加到 std::vector

    我想添加operator lt lt to std vector
  • Qt - QProcess 不工作

    我尝试启动 Internet Explorer 所以我使用下面的代码 QProcess process new QProcess this QString temp C Program Files Internet Explorer iex
  • Grpc - 将消息从一个客户端发送到连接到同一服务器的另一个客户端

    是否可以将消息从一个客户端发送到连接到同一服务器的另一个客户端 我想将数据从一个客户端发送到服务器然后发送到特定客户端 我想我需要获取客户端 ID 但我不知道如何获取此 ID 以及如何从服务器将此消息发送到该客户端 我这里有一个样本 这是一
  • Environment.CurrentDirectory 与 System.IO.Directory.GetCurrentDirectory

    我正在编写一个 Net WinForms 并不断在调试和发布配置之间切换 并且有一些文件我需要任一配置才能访问 我想做的是将文件放在 BIN 文件夹中的公共目录中 这样它看起来像这样 MyProject Bin CommonFiles My
  • 传递 constexpr 对象

    我决定给予新的C 14的定义constexpr旋转并充分利用它 我决定编写一个小的编译时字符串解析器 然而 我正在努力保持我的对象constexpr将其传递给函数时 考虑以下代码 include
  • java中如何重新初始化int数组

    class PassingRefByVal static void Change int pArray pArray 0 888 This change affects the original element pArray new int
  • 无法注册时间触发的后台任务

    对于 Windows 8 应用程序 在 C Xaml 中 我尝试注册后台任务 很难说 但我想我的后台任务已正确注册 但是当我单击调试位置工具栏上的后台任务名称时 我的应用程序停止工作 没有任何消息 我查看了事件查看器上的日志 得到 具有入口
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • 在 C# 中检查 PowerShell 执行策略的最佳方法是什么?

    当你跑步时Get ExecutionPolicy在 PowerShell 中 它得到有效的执行政策 https learn microsoft com en us powershell module microsoft powershell
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 从网页运行 ClickOnce 应用程序,无需用户操作

    我们有一个基于 Java 的 Web 应用程序以及用 C 编写的相同应用程序 如果 java 检查器发现客户端计算机上没有安装 Java 则应该运行该应用程序 这个想法是运行 C 单击一次 http en wikipedia org wik
  • 在 .NET MAUI 中实现 TouchTracking

    我一直致力于将我们的应用程序从 Xamarin Forms 迁移到 NET MAUI 我们的应用程序几乎没有绘图功能 用户可以用手指进行绘图 我们用了TouchTrackingXamarin Forms 中的 nuget 包 但与 NET
  • 如何递归取消引用指针(C++03)?

    我正在尝试在 C 中递归地取消引用指针 如果传递一个对象 那就是not一个指针 这包括智能指针 我只想返回对象本身 如果可能的话通过引用返回 我有这个代码 template
  • 从 C# 使用 Odbc 调用 Oracle 包函数

    我在 Oracle 包中定义了一个函数 CREATE OR REPLACE PACKAGE BODY TESTUSER TESTPKG as FUNCTION testfunc n IN NUMBER RETURN NUMBER as be
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • C++:为什么 numeric_limits 对它不知道的类型起作用?

    我创建了自己的类型 没有任何比较器 也没有专门化std numeric limits 尽管如此 由于某种原因 std numeric limits
  • 没有“对 *this”功能的右值引用的解决方法

    我有一个围绕可移动对象的代理容器类 并希望代理能够隐式生成对底层对象的右值引用 但仅当代理本身被移动时 我相信我将能够按照提案 n2439 实施此行为 将移动语义扩展到 this http www open std org jtc1 sc2
  • 为什么空循环使用如此多的处理器时间?

    如果我的代码中有一个空的 while 循环 例如 while true 它将把处理器的使用率提高到大约 25 但是 如果我执行以下操作 while true Sleep 1 它只会使用大约1 那么这是为什么呢 更新 感谢所有精彩的回复 但我
  • 是否允许全局静态标识符以单个 _ 开头?

    换句话说 可能static 文件范围 全局变量恰好以一个下划线开头 而不会产生与 C 实现发生名称冲突的可能性 https www gnu org software libc manual html node Reserved Names

随机推荐