c ++ static const std :: map using std :: make_pair,stop segfaults

时间:2014-09-05 04:06:13

标签: c++ multithreading c++11 map stl

我有一个stl map容器,我需要在初始化后只读(读取:线程安全),以防止我的某个程序的线程可能出现试图改变它,从而导致竞争条件。此地图使用std::make_pair。 目前,我有三个地图,都被声明为类mmapper的静态成员,以相同的方式实现,只是具有不同的值:

class mmapper {
        public:
                mmapper();
                std::string getKeyFromMap( const int &key1, const int &key2, const int &mid );
                static std::map<RgCodeUidPair, std::string> siteMap;
                static std::map<TPCodeUidPair, std::string> cachedData;
                static std::map<DLpair, std::string> Ddlabel;
        private:
                void createTypeMap();
                void createSiteMap();
                void createDriveLetterMap();
};



typedef std::pair<int, int> TPCodeUidPair;
typedef std::pair<int, int> RgCodeUidPair;
typedef std::pair<int, int> DLpair;
void mmapper::createSiteMap() {
                logger _logger( glob.g_ll, glob.g_logfile );
                _logger.logstream << "Loading Site Map.";
                _logger.log( 0 );
        if ( siteMap.empty() ) {
                siteMap.insert(std::make_pair(std::make_pair(0, 0), "AUS"));
                siteMap.insert(std::make_pair(std::make_pair(0, 1), "AUS2"));
                siteMap.insert(std::make_pair(std::make_pair(1, 0), "DCA"));
                siteMap.insert(std::make_pair(std::make_pair(1, 1), "DCA1"));
                siteMap.insert(std::make_pair(std::make_pair(1, 2), "DCA2"));
                siteMap.insert(std::make_pair(std::make_pair(1, 3), "DCA3"));
                siteMap.insert(std::make_pair(std::make_pair(1, 4), "DCAg"));
                siteMap.insert(std::make_pair(std::make_pair(1, 4), "LAX"));
                siteMap.insert(std::make_pair(std::make_pair(1, 5), "MIA"));
                siteMap.insert(std::make_pair(std::make_pair(1, 6), "TOR"));
                siteMap.insert(std::make_pair(std::make_pair(1, 7), "NYC"));
                siteMap.insert(std::make_pair(std::make_pair(2, 0), "AMS"));
                siteMap.insert(std::make_pair(std::make_pair(2, 1), "AMS1"));
                siteMap.insert(std::make_pair(std::make_pair(2, 2), "AMS2"));
                siteMap.insert(std::make_pair(std::make_pair(2, 3), "AMS3"));
                siteMap.insert(std::make_pair(std::make_pair(2, 4), "LON"));
                siteMap.insert(std::make_pair(std::make_pair(2, 5), "ZUR"));
                siteMap.insert(std::make_pair(std::make_pair(2, 6), "WAR"));
                siteMap.insert(std::make_pair(std::make_pair(3, 0), "HKG"));
                siteMap.insert(std::make_pair(std::make_pair(3, 1), "SGP"));
                siteMap.insert(std::make_pair(std::make_pair(3, 2), "TOK"));
                siteMap.insert(std::make_pair(std::make_pair(3, 3), "SYD"));
        }
}

这些由一个访问函数解析:

std::string mmapper::getKeyFromMap( const int &key1, const int &key2, const int &mid ) {
        logger _logger( glob.g_ll, glob.g_logfile );
        switch( mid ) {
                case 1: {
                        _logger.logstream << "Retrieving key values for Server Type.";
                        _logger.log( 1 );
                        auto it = cachedData.find(std::make_pair(key1, key2));
                        if( it != cachedData.end() ) {
                                _logger.logstream << "Successfully retrieved key value";
                _logger.log( 1 );
                                return it->second;
                        }
                        else {
                                _logger.logstream << "Failed to retrieve key.";
                _logger.log( 3 );
                                return "ERR";
                        }
                        break;
                }
                case 2: {
                        _logger.logstream << "Retrieving key values for Server Site.";
                        _logger.log( 1 );
                        auto it = siteMap.find(std::make_pair(key1, key2));
                        if( it != siteMap.end() ) {
                                _logger.logstream << "Successfully retrieved key value";
                                _logger.log( 1 );
                                return it->second;
                        }
                        else {
                                _logger.logstream << "Failed to retrieve key.";
                                _logger.log( 3 );
                                return "ERR";
                        }
                        break;
                }
                case 3: {
                        _logger.logstream << "Retrieveing key values for drive label";
                                _logger.log( 1 );
                        auto it = Ddlabel.find( std::make_pair( key1, key2 ));
                        if( it != Ddlabel.end() ) {
                                _logger.logstream << "Successfully retrieved key value";
                                _logger.log( 1 );
                                return it->second;
                        }
                        else {
                                _logger.logstream << "Failed to retrieve key.";
                _logger.log( 3 );
                                return "ERR";
                        }
                        break;
                }
                default:
                        _logger.logstream << "Invalid value passed to mapper! Err 3";
                        _logger.log( 5 );
                        return "ERR";
        }
}

所以我的问题是,如何防止我的线程修改此线程?我在考虑让地图只是static const,但我不确定如何使用std::pair实现这些地图。

我通常不会在乎,但这会在约20分钟后不断抛出段错误。 :(

这是回溯:

    at /usr/src/debug/gcc-4.4.7-20120601/obj-x86_64-redhat-linux/x86_64-redhat-linux/libstdc++-v3/include/bits/basic_string.tcc:174
#1  0x000000000040f47c in mmapper::getKeyFromMap (this=0x7fff42554ccf, key1=@0x7fffac012f60, key2=@0x7fffac012f64,
    mid=@0x7fff42554cec) at include/mmapper.cpp:65
#2  0x0000000000436bee in ddrive::readDriveData (this=0x7fff425550b0, data1=
    std::vector of length 576, capacity 1024 = {...}, db=...) at include/drive.cpp:83
#3  0x00000000004162f2 in handle_data(std::vector<int, std::allocator<int> >&) ()
#4  0x0000000000416fd7 in session(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >) ()
#5  0x00000000004249ac in void boost::_bi::list1<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > >::operator()<void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list0>(boost::_bi::type<void>, void (*&)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list0&, int) ()
#6  0x00000000004247bf in boost::_bi::bind_t<void, void (*)(boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > >), boost::_bi::list1<boost::_bi::value<boost::shared_ptr<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> > > > > >::operator()() ()

1 个答案:

答案 0 :(得分:1)

如果在初始化后再也没有再次更改mmapper,我只能在mmapper::getKeyFromMap()看到两个故障点:

  1. 参数。所有这些都是对外部数据的引用。如果删除外部数据,则可能发生随机异常。将它们从const int&更改为int。 “按值传递”是原始类型(check this post)的最佳方法。

  2. 记录器。你确定它的实现是线程安全的吗?它的内部数据正在频繁变化,因此它是一个很好的失败点。

  3. 异常似乎来自basic_string.tcc第174行,由mmapper第65行调用。这些行可能会为您提供更好的问题线索。