【问题标题】:Why does STL map core dump on find?为什么 STL 在 find 上映射核心转储?
【发布时间】:2009-01-26 19:58:32
【问题描述】:

所以,我遇到了这种情况,我需要查看一个对象是否在我的 stl 映射中。如果不是,我会添加它。

char symbolName[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
map<string,TheObject> theMap;
if (theMap.find(symbolName)==theMap.end()) {
            TheObject theObject(symbolName);
            theMap.insert(pair<string, TheObject>(symbolName,
                    theObject));
}

当对象不在地图中时,我在 theMap.find 上获得核心转储。 假设,如果项目不在地图中,它应该返回一个等效于 map::end 的迭代器

这是怎么回事?

GCC:3.4.6

【问题讨论】:

  • 嗯...知道TheObject::TheObject(???) 是什么会有所帮助。
  • 附带说明,你可以只做 char symbolName[] = "Hello";
  • 不管它是什么?它只是一个被“散列”的对象。
  • 地图可以实现为二叉树
  • 几乎可以肯定它是作为二叉树实现的。

标签: c++ gcc map


【解决方案1】:

它可能由于多种原因而崩溃。在不知道至少TheObject 的构造函数的定义的情况下,我认为我们在很大程度上只能猜测这个问题。到目前为止,您的代码看起来不错,但可以简化:

char symbolName[] = "Hello";
map<string,TheObject> theMap;
theMap.insert(make_pair(symbolName, TheObject(symbolName)));

如果符号已经被映射,它不会做任何事情,丢弃新的 TheObject 对象。

【讨论】:

    【解决方案2】:

    为什么不这样做呢?

    char symbolName[] = "hello";
    theMap.insert(pair<string, TheObject>(symbolName, TheObject(symbolName)));
    

    如果您的地图是map&lt;string, TheObject&gt;,那么如果您尝试搜索 NULL,您将获得核心转储:

    // This will core dump:
    char *symbolName = NULL; // Oops!
    theMap.find(symbolName); // Kabang!
    

    【讨论】:

    • 如果只是插入 TheObject(symbolName) 并且已经有该 symbolName 的 TheObject 实例,那么它将覆盖它。
    • 不,如果密钥已经存在,insert 不会做任何事情(在返回的对中的第二个值中由 false 表示。)
    • +1 好一个 Josh - 为什么要在 STL 为您进行检查时编写所有额外的代码
    【解决方案3】:

    在执行 find() 之前检查您的 STL 映射是否为空()。在空的 STL 映射上执行 find() 时,一些 STL 实现存在错误。

    【讨论】:

    • 它几乎肯定是空的。这是一个问题吗?为什么?
    • 我对这种情况出现的频率有疑问,但这个帖子谈到了这样的事情:velocityreviews.com/forums/…
    【解决方案4】:

    顺便说一下,有两种可能的简化。

    首先,使用make_pair 而不是pair 构造函数。这意味着您不必显式指定类型参数:

    theMap.insert(make_pair(symbolName, theObject));
    

    其次,您可以简单地编写代码,而不是编写代码:

    theMap[symbolName] = theObject;
    

    【讨论】:

    • IIRC,如果映射中不存在键,则使用方括号运算符访问 STL 映射返回 NULL 或引发异常 - 无论哪种方式,赋值的最终结果都是您得到一个异常.
    • 否 - 如果需要,它将使用 values 默认构造函数创建条目。
    • @rmeador:没有。括号运算符具有这个非常重要且被广泛忽略的副作用。这就是这个运算符没有const 版本的原因,这个事实令人无休止地激怒。
    • 然而,它将覆盖任何先前存储的 TheObject 对象。如果它有可变状态,它可能会改变事情。
    • 我的立场是正确的,刚刚阅读了文档......我也知道我遇到了我在第一条评论中描述的情况。我能想到的唯一解释是我在地图中的类型没有默认构造函数,但我怀疑这是否会编译...
    【解决方案5】:

    发布您的真实代码,或者至少是展示您所描述行为的完整示例。有时,当您尝试调试只是为了在此类论坛上发布而编写的虚构代码时,问题会在翻译中丢失。

    【讨论】:

      【解决方案6】:

      这段代码应该可以正常工作。

      唯一可能的问题是在 TheObject 实现内部,但它不应该影响 find 调用。

      另外,可能是一些不相关的问题,例如Buffer overflow,因为它之前执行了一些代码。

      【讨论】:

      • 它不起作用。 Codelogic 提到如果启动树为空可能会出现问题,但我不知道为什么。
      • 可以添加TheObject类的定义吗?你用的是什么编译器?
      • 我无法添加类的定义。编译器版本为 gcc 3.4.6
      【解决方案7】:

      作为代码简化的补充:

      使用 std::string 代替 char[] 并在 TheObject 的类定义中使用它。

      不确定您的 TheObject 类使用 char 数组在做什么,但如果您在此函数范围之外使用地图,例如。通过将其用作返回值,我敢打赌某处有一个对象指向 symbolName 的地址,该地址不再定义。

      【讨论】:

        【解决方案8】:

        我不知道你为什么会得到核心转储;该代码对我有用。

        有机会让您的代码更简单、更易读:

        • 正如其他人所说,您可以将插入简化为theMap[symbolName] = TheObject(symbolName)

        • 我可能错了,但据我所知 { 'a', 'b', '\0' } 与 "abc" 相同,因此您可以简化为 char symbolName[] = "Hello"; 我有印象中非惯用的定义在这里让一些人感到困惑。

        【讨论】:

          【解决方案9】:

          检查你是否在构造函数中使用它。在构造函数中使用 map 时,我遇到了类似的问题。

          【讨论】:

            【解决方案10】:

            我通过使用指向我的地图对象的指针来解决我的问题。由于在构造函数中使用,它们需要是指针,然后在构造函数中我对它们进行了新的操作。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-11-19
              • 2017-01-26
              • 1970-01-01
              相关资源
              最近更新 更多