从unordered_multiset读取会导致崩溃

时间:2015-12-18 10:52:46

标签: c++ c++11 hashmap unordered

在重构一些旧代码时,一个繁琐的多层映射开发内部std::undordered_multiset取代。

多级地图就像[string_key1,string_val]。应用了一个复杂的算法来从string_val导出密钥,并导致重复的string_val存储在地图中但具有不同的密钥。

最终,在应用程序的某个时刻,迭代了多级映射以获取string_val及其出现次数。

替换为std::unordered_multilevelset,只插入了string_val。它似乎比拥有std::map<std::string,int>和检查 - 检索 - 更新每个插入的计数器简单得多。

我想要做的是检索其插入元素的出现次数,但我没有前面的键。所以我迭代了桶,但我的程序在创建字符串时崩溃了。

// hash map declaration
std::unordered_multiset<std::string> clevel;

// get element and occurences
for (size_t cbucket = clevel->bucket_count() - 1; cbucket != 0; --cbucket)
{
        std::string cmsg(*clevel->begin(cbucket));
        cmsg += t_str("times=") + \
                std::to_string(clevel->bucket_size(cbucket));
}

我不明白这里发生了什么,试图调试它,但我不知何故堆栈(溢出?):)。程序在std::string cmsg(*it);

中崩溃

1 个答案:

答案 0 :(得分:2)

您应该考虑multiset实际上如何作为哈希表。例如,阅读此introduction您应该注意到哈希映射实际上预先分配了它们的内部桶,并且优化了桶的数量。

因此,如果您插入元素“hello”,您可能会获得许多已创建的存储桶,但只有与hash("hello")对应的存储桶实际上会有一个您可以取消引用的元素。其余的将被视为无效。

取消引用迭代器到每个存储桶的开头会产生SEGV,这就是你的情况。

要解决这种情况,每次开始时都应该检查结束。

for (size_t cbucket = clevel->bucket_count() - 1; cbucket != 0; --cbucket)
{
    auto it = clevel->begin(cbucket);
    if (it != clevel->end(cbucket))
    {
        std::string cmsg(*it);
        cmsg += t_str("times=") + \
                std::to_string(clevel->bucket_size(cbucket));
    }
}