奇怪无序的地图情况 [英] Strange unordered map situation

查看:134
本文介绍了奇怪无序的地图情况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个共享的图书馆类:

  // HPP:
class WorldSettings
{
private:
static std :: unordered_map< std :: string,int> mIntegerStorage;
static std :: unordered_map< std :: string,float> mFloatStorage;
static std :: unordered_map< std :: string,std :: string> mStringStorage;

public:
template< typename T>
static T& Get(const std :: string& key);

模板< typename T>
static T& Set(const std :: string& key,T value);
};

// CPP:

  #define DoReturn(MapName,Key,Type){\ 
assert(MapName.find(Key)!= MapName.end()&&& !); \
return MapName [Key]; \
} \

#define DoSetup(MapName,Key,Value){\
MapName [key] = Value; \
return MapName [Key]; \
} \

std :: unordered_map< std :: string,int> WorldSettings :: mIntegerStorage;
std :: unordered_map< std :: string,float> WorldSettings :: mFloatStorage;
std :: unordered_map< std :: string,std :: string> WorldSettings :: mStringStorage;

// Getters

template<>
int& WorldSettings :: Get< int>(const std :: string& key)
{
DoReturn(mIntegerStorage,key,int);
}

template<>
float& WorldSettings :: Get< float>(const std :: string& key)
{
DoReturn(mFloatStorage,key,float);
}

template<>
std :: string& WorldSettings :: Get< std :: string>(const std :: string& key)
{
DoReturn(mStringStorage,key,std :: string) ;
}

// Setters

template<>
int& WorldSettings :: Set< int>(const std :: string& key,int value)
{
DoSetup(mIntegerStorage,key,value);
}

template<>
float& WorldSettings :: Set< float>(const std :: string& key,float value)
{
DoSetup(mFloatStorage,key,value);
}

template<>
std :: string& WorldSettings :: Set< std :: string>(const std :: string& key,std :: string value)
{
DoSetup(mStringStorage,key ,价值);
}

现在我想在非共享库中使用这个类(简单的控制台应用程序) :

  WorldSettings :: Get< int>(WorldMinutes); 

'WorldMinutes'设置在共享库代码中:

  WorldSettings :: Set< int>(WorldMinutes,0); 

问题是:


浮点异常




 程序接收信号SIGFPE,算术异常。 
0x00000000004d1f61 in std :: __ detail :: _ Mod_range_hashing :: operator()(this = 0x747863,__num = 732984944481197501,
__den = 0)at / usr / lib / gcc / x86_64-unknown-linux-gnu /4.6.2/../../../../include/c++/4.6.2/bits/hashtable_policy.h:376
376 {return __num%__den;

追溯:

在/ usr / lib / gcc / x86_64-unknown中的std :: __ detail :: _ Mod_range_hashing :: operator()(this = 0x747863,__num = 732984944481197501,
__den = 0)中的#0 0x00000000004d1f61 -linux-gnu / 4.6.2 /../../../../ include / c ++ / 4.6.2 / bits / hashtable_policy.h:376
#1 0x00000000004d3503 in std :: __ detail :: _Hash_code_base< std :: string,std :: pair< std :: string const,int>,std :: _ Select1st< std :: pair< std :: string const,int> > std :: equal_to< std :: string>,std :: hash< std :: string>,std :: __ detail :: _ Mod_range_hashing,std :: __ detail :: _ Default_ranged_hash,false> :: _ M_bucket_index(this = 0x747860 ,__c = 732984944481197501,__n = 0)
at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../include/c++/4.6 .2 / bits / hashtable_policy.h:758
#2 std :: __ detail :: _ Map_base< std :: string,std :: pair< std :: string中的0x00000000004d2a9a,const< std :: _ Select1st& std :: pair< std :: string const,int> > true,std :: _ Hashtable< std :: string,std :: pair< std :: string const,int>,std :: allocator< std :: pair< std :: string const,int> > std :: _ Select1st< std :: pair< std :: string const,int> > std :: equal_to< std :: string>,std :: hash< std :: string>,std :: __ detail :: _ Mod_range_hashing,std :: __ detail :: _ Default_ranged_hash,std :: __ detail :: _ Prime_rehash_policy,false ,false,true> > :: operator [](this = 0x747860,__k = ...)
at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../ .. /../include/c++/4.6.2/bits/hashtable_policy.h:543
#3 0x00000000004d1cfa在WorldSettings :: Set< int> (key = ...,value = 0)

在共享库代码中设置< int>(...)。有趣的是,当从库代码调用 Get 时,我没有错误。这里有什么问题?

解决方案

代码不正确。



。您在.cpp文件中定义的专业版应该已经在.hpp文件中被声明(除了类之外),否则任何时候你尝试使用定义的函数,你有未定义的行为。



添加:

 模板<> 
int& WorldSettings :: Get< int>(const std :: string& key);

template<>
float& WorldSettings :: Get< float>(const std :: string& key);

template<>
std :: string& WorldSettings :: Get< std :: string>(const std :: string& key);

// Setters

template<>
int& WorldSettings :: Set< int>(const std :: string& key,int value);

template<>
float& WorldSettings :: Set< float>(const std :: string& key,float value);

template<>
std :: string& WorldSettings :: Set< std :: string>(const std :: string& key,std :: string value);

在类定义之后。



这就告诉编译器这些定义是在其他地方生成的。



因此,共享库可能会生成自己的函数副本(你提供了一些默认模板实现?),这可能会导致破坏。



这可能不是错误的原因,但进一步调查是没有意义的。

I have a shared library with class:

// HPP:
class WorldSettings
{
    private:
        static std::unordered_map<std::string, int> mIntegerStorage;
        static std::unordered_map<std::string, float> mFloatStorage;
        static std::unordered_map<std::string, std::string> mStringStorage;

    public:
        template <typename T>
        static T &Get(const std::string &key);

        template <typename T>
        static T &Set(const std::string &key, T value);
};

// CPP:

#define DoReturn(MapName, Key, Type) {                                                \
    assert( MapName.find(Key) != MapName.end() && "No such key in world settings!" ); \
    return MapName[Key];                                                              \
}                                                                                     \

#define DoSetup(MapName, Key, Value) { \
    MapName[key] = Value;              \
    return MapName[Key];               \
}                                      \

std::unordered_map<std::string, int> WorldSettings::mIntegerStorage;
std::unordered_map<std::string, float> WorldSettings::mFloatStorage;
std::unordered_map<std::string, std::string> WorldSettings::mStringStorage;

// Getters

template <>
int &WorldSettings::Get<int>(const std::string &key)
{
    DoReturn(mIntegerStorage, key, int);
}

template <>
float &WorldSettings::Get<float>(const std::string &key)
{
    DoReturn(mFloatStorage, key, float);
}

template <>
std::string &WorldSettings::Get<std::string>(const std::string &key)
{
    DoReturn(mStringStorage, key, std::string);
}

// Setters

template <>
int &WorldSettings::Set<int>(const std::string &key, int value)
{
    DoSetup(mIntegerStorage, key, value);
}

template <>
float &WorldSettings::Set<float>(const std::string &key, float value)
{
    DoSetup(mFloatStorage, key, value);
}

template <>
std::string &WorldSettings::Set<std::string>(const std::string &key, std::string value)
{
    DoSetup(mStringStorage, key, value);
}

Now I want to use this class in non shared library (simple console application):

WorldSettings::Get<int>("WorldMinutes");

The 'WorldMinutes' is set in shared library code:

WorldSettings::Set<int>("WorldMinutes", 0);

The problem is:

Floating point exception

Program received signal SIGFPE, Arithmetic exception.
0x00000000004d1f61 in std::__detail::_Mod_range_hashing::operator() (this=0x747863, __num=732984944481197501, 
    __den=0) at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../include/c++/4.6.2/bits/hashtable_policy.h:376
376     { return __num % __den; }

Backtrace:

#0  0x00000000004d1f61 in std::__detail::_Mod_range_hashing::operator() (this=0x747863, __num=732984944481197501, 
    __den=0) at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../include/c++/4.6.2/bits/hashtable_policy.h:376
#1  0x00000000004d3503 in std::__detail::_Hash_code_base<std::string, std::pair<std::string const, int>, std::_Select1st<std::pair<std::string const, int> >, std::equal_to<std::string>, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, false>::_M_bucket_index (this=0x747860, __c=732984944481197501, __n=0)
    at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../include/c++/4.6.2/bits/hashtable_policy.h:758
#2  0x00000000004d2a9a in std::__detail::_Map_base<std::string, std::pair<std::string const, int>, std::_Select1st<std::pair<std::string const, int> >, true, std::_Hashtable<std::string, std::pair<std::string const, int>, std::allocator<std::pair<std::string const, int> >, std::_Select1st<std::pair<std::string const, int> >, std::equal_to<std::string>, std::hash<std::string>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, false, false, true> >::operator[] (this=0x747860, __k=...)
    at /usr/lib/gcc/x86_64-unknown-linux-gnu/4.6.2/../../../../include/c++/4.6.2/bits/hashtable_policy.h:543
#3  0x00000000004d1cfa in WorldSettings::Set<int> (key=..., value=0)

The error is called when Set<int>(...) in shared library code. The interesting thing is that I don't have an error when call Get from library code. What could be wrong here?

解决方案

The code is incorrect as it is.

The specializations you define in the .cpp file should have been declared (out of the class) in the .hpp file, otherwise any time you try to use the defined function you have undefined behavior.

Add:

template <>
int &WorldSettings::Get<int>(const std::string &key);

template <>
float &WorldSettings::Get<float>(const std::string &key);

template <>
std::string &WorldSettings::Get<std::string>(const std::string &key);

// Setters

template <>
int &WorldSettings::Set<int>(const std::string &key, int value);

template <>
float &WorldSettings::Set<float>(const std::string &key, float value);

template <>
std::string &WorldSettings::Set<std::string>(const std::string &key, std::string value);

right after the class definition.

This tells the compiler that the definitions are generated elsewhere.

As it is, it is likely that the shared library will generate its own copy of the functions (did you provided some default template implementation ?) and that may cause havoc.

It may not be the cause of the bug, but it does not make sense to investigate further.

这篇关于奇怪无序的地图情况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆