在结构数组中访问 std::unordered_map 时出现浮点错误

Floating point error when accessing std::unordered_map in array of structs

本文关键字:错误 map unordered 数组 结构 访问 std      更新时间:2023-10-16

我的代码生成一个结构的C数组,其中结构的一个成员是STL std::unordered_map:

typedef struct test_s {
   int count_a;
   std::unordered_map<std::string, int> my_map;
} test_map;
typedef struct cm_example {
   int width;
   test_map *counts;
   unsigned int hasha, hashb;
} cm_sketch;

但是,当我尝试访问地图以执行查找,插入等时。我总是遇到浮点异常:

Compile:  g++ -std=c++11 -g test_struct.cpp -o h_str
Run:  ./h_str_str agggcctttgagag 100
Output: 
Kmer name: agggcctttgagag
hash_a: 172110908 , hash_b: 1954003865, bucket: 92 
Floating point exception

我的代码如下:

cm_sketch *cm_init (int width, int seed)
{
    cm_sketch *cm;
    int i=0;
    cm = (cm_sketch *) malloc(sizeof(cm_sketch));
    cm->width = width;
    cm->counts = (test_map *) malloc (sizeof(test_map) * width);
    for (i=0; i<width; i++) {
         cm->counts[i].count_a = 0;
    }
    cm->hasha = 172110908;
    cm->hashb = 1954003865;
    return cm;
 }
 int main(int argc, char *argv[])
 {
    int bucket_id=0;
    if (argc < 2)
    {
            printf ("Please provide correct number of input arguments: n");
            printf ("./exe 1:k-mer 2:wn");
            exit (0);
    }
    char *kmer_input = argv[1];
    int width = atoi(argv[2]);
    std::string kmer_name = kmer_input;
    std::cout << "Kmer name: " << kmer_name;
    printf("n");
    cm_sketch *cm = cm_init(width, time(NULL));
    unsigned int hashval = hash_str(kmer_input);
    bucket_id = hash31(cm->hasha, cm->hashb, hashval) % cm->width;
    std::unordered_map<std::string, int>::const_iterator got;
    printf ("hash_a: %d , hash_b: %d, bucket: %d n", cm->hasha, cm->hashb, bucket_id);
    got = cm->counts[bucket_id].my_map.find(kmer_name); /* FLOATING POINT ERROR */
    if (got == cm->counts[bucket_id].my_map.end())
        cm->counts[bucket_id].my_map[kmer_name] = 1;
    else
        cm->counts[bucket_id].my_map[kmer_name]++;
   // Iterate and print keys and values of unordered_map
   for( const auto& n : cm->counts[bucket_id].my_map ) {
        std::cout << "Key:[" << n.first << "] Value:[" << n.second << "]n";
   }
   return 0;
 }

浮点误差可能是"除以零"的原因。但是,这里的错误是内部的。在 gdb 中运行给出了以下内容:

Program received signal SIGFPE, Arithmetic exception.
0x00000000004018f1 in std::__detail::_Mod_range_hashing::operator()    (this=0x607768, __num=10758833940372818866, __den=0)
at /opt/gcc/4.9.3/snos/include/g++/bits/hashtable_policy.h:449
449     { return __num % __den; }
(gdb) bt
#0  0x00000000004018f1 in std::__detail::_Mod_range_hashing::operator() (this=0x607768, __num=10758833940372818866, __den=0)
at /opt/gcc/4.9.3/snos/include/g++/bits/hashtable_policy.h:449
#1  0x00000000004021cc in std::__detail::_Hash_code_base<std::string, std::pair<std::string const, int>, std::__detail::_Select1st, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>::_M_bucket_index (this=0x607768, 
__c=10758833940372818866, __n=0) at /opt/gcc/4.9.3/snos/include/g++/bits/hashtable_policy.h:1266
#2  0x0000000000401d68 in std::_Hashtable<std::string, std::pair<std::string const, int>, std::allocator<std::pair<std::string const, int> >, std::__detail::_Select1st, std::equal_to<std::string>, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::_M_bucket_index (this=0x607768, __k=..., 
__c=10758833940372818866) at /opt/gcc/4.9.3/snos/include/g++/bits/hashtable.h:614
#3  0x0000000000401ac6 in std::_Hashtable<std::string, std::pair<std::string const, int>, std::allocator<std::pair<std::string const, int> >, std::__detail::_Select1st, std::equal_to<std::string>, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<true, false, true> >::find (this=0x607768, __k=...)
at /opt/gcc/4.9.3/snos/include/g++/bits/hashtable.h:1303
#4  0x0000000000401969 in std::unordered_map<std::string, int, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, int> > >::find (this=0x607768, __x=...) at /opt/gcc/4.9.3/snos/include/g++/bits/unordered_map.h:574
#5  0x00000000004015cb in main (argc=3, argv=0x7fffffff7618) at test_struct.cpp:100

我对C++不是很熟悉,而且我一直在为这段代码而苦苦挣扎。请帮助隔离错误。我错过了什么吗?我是否正确访问hash_map条目?

您的代码具有未定义的行为。 当您使用

cm = (cm_sketch *) malloc(sizeof(cm_sketch));

您为cm_sketch分配了足够的存储空间,并且必须指向它cmmalloc 虽然不会为您创建的对象调用构造函数。 所以现在你有一个对象,其中所有成员都未初始化。 使用这些未初始化的变量是未定义的行为。

如果需要指针和动态内存分配,则应使用 new 来分配存储,并在完成后使用 delete 来释放它。 new将调用构造函数以确保您创建的对象已初始化,delete将调用析构函数,该析构函数将销毁类包含的所有成员。