为啥 STL 在 find 上映射核心转储?

Posted

技术标签:

【中文标题】为啥 STL 在 find 上映射核心转储?【英文标题】: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"; 不管它是什么?它只是一个被“散列”的对象。 地图可以实现为二叉树 几乎可以肯定它是作为二叉树实现的。 【参考方案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】:

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

【讨论】:

以上是关于为啥 STL 在 find 上映射核心转储?的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个核心转储错误发生在我的课堂上?我已经包含了复制构造函数、复制赋值和析构函数

为啥核心转储?

为啥我得到分段(核心转储)?

为啥我的代码结果显示分段错误(核心转储)?

为啥在构建 Android 11 时出现非法指令(核心转储)错误?

为啥会生成此核心转储