读取 unordered_multiset 导致崩溃
Reading from unordered_multiset results in crash
在重构一些旧代码时,内部 开发的繁琐多级地图被 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);
时崩溃
您应该考虑 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));
}
}
在重构一些旧代码时,内部 开发的繁琐多级地图被 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);
您应该考虑 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));
}
}