【问题标题】:C++ 11 unordered_map.find exceptionC++ 11 unordered_map.find 异常
【发布时间】:2019-01-25 00:46:22
【问题描述】:

最新的简化代码,在 emplace 调用中崩溃:程序收到信号 SIGSEGV,分段错误。

#include <utility>
#include <string>
#include <iostream>
#include <map>
#include <unordered_map>
#include <set>
#include <algorithm>

using namespace std;
struct test
{
    int x;
    int *y;
    map<string, uintptr_t> m;
};

int main ()
{

    int x=11,y=22;
    void *x1 = &x, *y1=&y;

    test *t1 = static_cast<test*>(calloc(1,sizeof(test)));
    t1->m.emplace(string("x"),reinterpret_cast<std::uintptr_t>(x1));
    t1->m.emplace(string("y"),reinterpret_cast<std::uintptr_t>(y1));

  return 0;
}

================下面是之前的代码crash=====

C++11 unordered_map find 调用抛出: 程序以信号 8 终止,算术异常。 在 linux C++ 代码中围绕 void * 和 uintptr_t 进行了更改。由于历史原因,uintptr_t 类型供我转换为/从 void * 指针。

unordered_map<string, uintptr_t> channels;
...
auto itr = channels.find(string("abc"));

它在地图为空的第一次调用中崩溃。它编译。 GDB 转储:

(gdb) BT #0 0x000000000047457d in std::__detail::_Mod_range_hashing::operator() (this=0x2ad198001aa0, __num=8205015523586275093, __den=0) 在 /usr/include/c++/4.8.2/bits/hashtable_policy.h:345 #1 0x0000000000474c83 在 std::__detail::_Hash_code_base, std::__detail::_Select1st, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>::_M_bucket_index ( this=0x2ad198001aa0, __c=8205015523586275093, __n=0) 在 /usr/include/c++/4.8.2/bits/hashtable_policy.h:1108 #2 0x000000000047493a 在 std::_Hashtable, std::allocator >, std::__detail::_Select1st, std::equal_to, std::hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std ::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::_M_bucket_index (this=0x2ad198001aa0, __k="nuance90-mrcp1", __c=8205015523586275093) 在/usr/include/c++/4.8.2/bits/hashtable .h:593 #3 0x00000000004747b0 在 std::_Hashtable、std::allocator >、std::__detail::_Select1st、std::equal_to、std::hash、std::__detail::_Mod_range_hashing、std::__detail::_Default_ranged_hash、std ::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits >::find (this=0x2ad198001aa0, __k="nuance90-mrcp1") at /usr/include/c++/4.8.2/bits/hashtable.h:1024 #4 0x00000000004745f5 in std::unordered_map, std::equal_to, std::allocator > >::find (this=0x2ad198001aa0, __x="abc") 在 /usr/include/c++/4.8.2/bits/unordered_map.h:543

【问题讨论】:

  • 演示问题的最小完整示例程序会很有用。
  • @Shawn [mcve] 扩展为 minimal reproducible example。非常方便,但请稍等! There's more!
  • @Charlie 这只是意味着您的代码中某处存在错误。如果您的代码很小,那么您可以发布它。如果您有很多代码,则需要使其大小合理(因此对 mcve 进行了注释)。在执行此操作(简化)的过程中,您可能会发现问题所在。这就是我们要求人们这样做的原因。
  • 大家好,感谢您的回复。我得到了简化,现在它在 emplace 调用中崩溃了。它编译。
  • calloc函数只分配内存,没有调用成员数据的构造函数,所以m没有正确初始化,调用test* t = new test;

标签: c++ exception math find unordered-map


【解决方案1】:

我想我找到了答案:c function calloc get you fixed size of memory,如果你在 c struct 中有一个 STL 容器,并且使用了 c calloc 函数,程序可能无法增加大小。这是有效的代码,请看区别:c 结构中包含的 STL 现在变成了指针。

#include <utility>      // std::pair, std::make_pair
#include <string>       // std::string
#include <iostream>     // std::cout
#include <map>
#include <unordered_map>
#include <set>
#include <algorithm>

using namespace std;
struct test
{
    int x;
    int *y;
    map<string, uintptr_t> *m;
};

int main ()
{
    int x=11,y=22;
    void *x1 = &x, *y1=&y;

    test *t1 = static_cast<test*>(calloc(1,sizeof(test)));
    t1->m = new map<string, uintptr_t>();
    t1->m->emplace(string("x"),reinterpret_cast<std::uintptr_t>(x1));
    t1->m->emplace(string("y"),reinterpret_cast<std::uintptr_t>(y1));

    cout<<"====== retrive the map in a calloc memory area==="<<endl;
    auto itr = t1->m->find(string("x"));
    if(itr != t1->m->end())
    {
        int *i = reinterpret_cast<int*>(itr->second);
        cout<<"found x="<<*i<<endl;
    }

  return 0;
}

【讨论】:

  • 正如@rafix07 提到的,STL 容器构造函数没有被 calloc 调用。
  • 这可行,但会给程序增加不必要的内存管理要求。现在必须手动删除所有test::m 成员。避免这样做。
  • 同意你的看法。 @用户4581301。我正在处理遗留的 c 代码
  • 将 C++ 代码插入 C 代码可能是个坏主意。坚持使用一种语言,或每个源文件至少使用一种语言。
猜你喜欢
  • 1970-01-01
  • 2019-12-08
  • 2011-01-22
  • 1970-01-01
  • 2011-03-30
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多