C++ C++;将元素指定给映射值时访问错误

C++ C++;将元素指定给映射值时访问错误,c++,dictionary,hashmap,exc-bad-access,C++,Dictionary,Hashmap,Exc Bad Access,所以这个问题解释了这个问题 背景: 我想从HackerRank那里解决这个问题 它基本上是一个html标记解析器。保证有效输入,属性仅为字符串 我的方法 我创建了一个自定义的Tag类,它可以存储其他Tag的map,以及属性的map。解析似乎工作正常 问题 在查询部分,我在下面的查询/html组合中得到一个BAD_ACCESS错误: 4 1 <a value = "GoodVal"> <b value = "BadVal" size = "10"> </b> &

所以这个问题解释了这个问题

背景: 我想从HackerRank那里解决这个问题

它基本上是一个html标记解析器。保证有效输入,属性仅为字符串

我的方法 我创建了一个自定义的
Tag
类,它可以存储其他
Tag
map
,以及属性的
map
。解析似乎工作正常

问题 在查询部分,我在下面的查询/html组合中得到一个
BAD_ACCESS
错误:

4 1
<a value = "GoodVal">
<b value = "BadVal" size = "10">
</b>
</a>
a.b~size
我试过的 只需定义
Tag x=t.tags[Tag_name]作为一个新变量,然后执行
t=x
此外,下面的查询也会失败:
a.b.c~height
,但在第99行尝试获取a.tags[“b”]时失败。不知道为什么。我本打算用上面的黑客补丁,但这似乎是一个大的核心问题,我做错了

我建议在IDE上运行它,并验证解析是否确实正确

t=t.tags[tag_name]
此表达式是不安全的,因为您正在将该对象所拥有的对象复制指定给所拥有的对象

考虑一下这一行发生了什么:

  • 执行地图查找并返回一个
    标记&
  • 您试图通过调用隐式复制分配运算符将其复制分配给
    t
  • 此操作员复制从复制源的
    tags
    属性分配
    t.tags
    ,复制源位于
    t.tags
  • 结果是您复制到的对象T在该副本的中间被破坏。这会导致未定义的行为,而立即崩溃确实是最好的结果,因为它会准确地告诉您问题所在。(这类问题经常在程序后期的某个时候出现,此时您已经失去了找出导致UB的原因所需的状态。)

    一种解决方法是将源对象移动到临时对象中,然后将该临时对象移动到
    t

    t = Tag{std::move(t.tags[tag_name])};
    
    这将在我们尝试将数据放入
    t
    之前,将要分配给
    t
    的数据从
    t
    中取出。然后,当
    t
    的赋值运算符转到replace
    t.tags
    时,您试图赋值给
    t
    的数据不再存在

    然而,这种总体方法涉及大量不必要的复制。最好将
    t
    声明为
    tagconst*t是一个指向标记的指针。然后,您可以将指针移动到数据结构中的其他标记,而无需复制



    旁注:前几天我刚解决了这个问题!这里有一个提示可以帮助你简化事情:你真的需要一个标签结构吗?是否有一种更简单的查找结构可以替代嵌套的标记?

    只要快速查看一下代码,“访问错误”的唯一可能性就是错误处理字符串,并假设您正在访问范围内的字符串。我怀疑这与
    std::map
    有关。例如,您执行
    find()
    ,但从不检查是否找到任何东西,您假设字符串至少有2个字符,而您有
    string[1]
    ,等等。除此之外,您在
    main
    中粘贴一段巨大的代码,而不是将代码分解为逻辑函数,从而使单元测试更容易。为什么确定
    是否存在的代码没有单独的功能?@PaulMcKenzie这是面试准备,所以我的目标是尽快得到一些信息。我知道样式很糟糕,但是字符串解析是正确的,我调试了代码,字符串键也是正确的。所以我认为这是一个内存问题,因为在访问之前,我确实会使用
    if(t.tags.find(tag_name)==t.tags.end())
    检查是否在映射中找到了密钥。给我们一个导致问题的示例文本,我敢打赌您的字符串解析失败。“这是面试准备,所以我的目标是尽快得到一些信息。”-你不认为面试官会根据你的代码质量来评价你吗?好吧,所以我成功了(3个小时后,因为你的帮助)。第一件事:非常感谢!第二,什么是更简单的查找结构?必须对父母的道路有一些了解。。。将父路径编码为字符串是否有效?因此,映射将是
    map
    ,关键点是整个路径作为字符串(我可以在创建过程中动态生成),对吗?在注释的最后一部分中,您可以动态地为每个属性(不仅仅是元素)构建查找键,因此,您需要的唯一结构是
    std::map
    。我应该澄清,这是执行查询所需的唯一查找结构。当然,在构建该结构时,您需要一个堆栈来维护嵌套的标记状态。当然,基本上代码的顶部部分保持不变(或多或少),除了我如何为属性设置关键帧,那么查询基本上是一个即时操作。我喜欢这个主意!您也可以使用
    std::hash_map
    进行O(1)查找(而不是
    std::map
    的O(logn)),但是构建映射可能需要更长的时间,因此它取决于查询数量和标记数据结构大小之间的差异。
    t = Tag{std::move(t.tags[tag_name])};