2010-07-08 85 views
2

我有一些代碼來處理資源(圖像,字體,網格數據等)管理使用模板的靜態類,允許客戶端代碼做類似:幫助理解std :: map/boost :: unordered_map

ResourceManager<Texture>::init("data/textures"); 
ResourceManager<Font>::init("data/fonts"); 
// later ... 
boost::shared_ptr<const Texture> tex = ResourceManager<Texture>::getResource("wall.png"); 
boost::shared_ptr<const Font> font = ResourceManager<Font>::getResource("Arial.ttf"); 
// later ... 
ResourceManager<Texture>::release(); 

「資源類型」必須有一個構造函數,採用const std::string&

getResource被實現如下:

static boost::shared_ptr<const ResourceType> getResource(const std::string& fileName) 
{ 
    boost::shared_ptr<ResourceType> resource; 

    typename table_t::const_iterator itr = _resources.find(fileName); 
    if (itr == _resources.end()) { 
     resource.reset(new ResourceType(_dataDirectory + fileName)); 
     _resources[fileName] = resource; 
    } else { 
     resource = itr->second; 
    } 

    return resource; 
} 

table_t被定義爲typedef typename boost::unordered_map< std::string, boost::shared_ptr<ResourceType> > table_t;

_resourcestable_t類型。

問題出在boost::unordered_map我在find(源自find_iterator)的調用中遇到段錯誤。但是,使用std::map代替,我可以在插入操作(源自_Rb_tree_decrement)或find(源自string::compare)的調用中獲得段錯誤。

問題只發生在 第二個時間資源被請求(fileName是有效的,當失敗發生時)。

因爲mapunordered_map發生這種情況,我假設我必須在某個地方做點奇怪的事情來引起這個,任何想法?

謝謝。

編輯:仍然有問題,我錯了它只發生第二次資源被請求。然而,前兩次獲取資源的調用是成功的,這是導致段錯誤的第三次調用(每次調用都是針對不同的資源)。

這裏是一個堆棧跟蹤:

Program received signal SIGSEGV, Segmentation fault. 
0x00000000004b4978 in boost::unordered_detail::hash_table<boost::unordered_detail::map<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, boost::shared_ptr<Texture> > > > >::find_iterator (this=0x7aed80, bucket=0x38, k=...) 
    at /usr/local/include/boost/unordered/detail/table.hpp:55 
55   node_ptr it = bucket->next_; 
(gdb) bt 
#0 0x00000000004b4978 in boost::unordered_detail::hash_table<boost::unordered_detail::map<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, boost::shared_ptr<Texture> > > > >::find_iterator (this=0x7aed80, bucket=0x38, k=...) 
    at /usr/local/include/boost/unordered/detail/table.hpp:55 
#1 0x00000000004b294c in boost::unordered_detail::hash_table<boost::unordered_detail::map<std::string, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, boost::shared_ptr<Texture> > > > >::find (this=0x7aed80, k=...) 
    at /usr/local/include/boost/unordered/detail/table.hpp:583 
#2 0x00000000004b07c1 in boost::unordered_map<std::string, boost::shared_ptr<Texture>, boost::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, boost::shared_ptr<Texture> > > >::find (this=0x7aed80, k=...) 
    at /usr/local/include/boost/unordered/unordered_map.hpp:423 
#3 0x00000000004ae7c6 in ResourceManager<Texture>::getResource (fileName=...) at /home/tim/Projects/gameproj/app/ResourceManager.hpp:52 
#4 0x00000000004ce7fc in Map::loadCellTextures (this=0x7fffffffdfc0, in=...) at /home/tim/Projects/gameproj/app/Map.cpp:57 
#5 0x00000000004ce632 in Map (this=0x7fffffffdfc0, fileName=...) at /home/tim/Projects/gameproj/app/Map.cpp:30 
#6 0x0000000000495702 in Game::init (xResolution=1024, yResolution=768) at /home/tim/Projects/gameproj/app/Game.cpp:116 
#7 0x0000000000494fa0 in Game::run (xResolution=1024, yResolution=768) at /home/tim/Projects/gameproj/app/Game.cpp:38 
#8 0x0000000000487f1d in Main::run (xResolution=1024, yResolution=768) at /home/tim/Projects/gameproj/app/Main.cpp:28 
#9 0x0000000000487db5 in main (argc=1, argv=0x7fffffffe398) at /home/tim/Projects/gameproj/app/main.cpp:10 
+0

_resources是如何聲明/初始化/銷燬/等? – ggiroux 2010-07-08 03:03:48

+0

sig11發生時從gdb添加回溯可以幫助診斷。 – ggiroux 2010-07-08 03:12:41

+0

'_resources'被聲明爲'static_table_t_resources;',並且初始化爲: 'template boost :: unordered_map > ResourceFactory :: _resources;低於類定義的' 。 有一個靜態'釋放'函數被調用來釋放資源,這隻需要使用'_resources.clear()'來完成。 – Tim 2010-07-08 03:41:05

回答

0

只出現問題的資源請求

這表明,我認爲你的代碼可能會釋放資源二號時間 - 第一次沒關係,然後你釋放它,然後下一次容器試圖訪問內存時,它會發生段錯誤。

2

我找不到任何明顯的錯誤,你試過Valgrind(假設你運行某種* nix系統)?這是查找內存錯誤的寶貴工具,看起來這可能就是其中之一。

+0

+1上運行良好,推薦valgrind,這是一個非常寶貴的工具,非常值得您花時間學習它。 – 2010-07-08 02:51:18

+0

,它也是最好的分析器! – Staffan 2010-07-08 02:57:09

+0

我對Valgrind有點熟悉,當發生段錯誤時,我收到'無效的8號讀取'。在table.hpp(boost的一部分)中,有問題的行是'node_ptr it = bucket-> next_;'。用調試器看起來'bucket'是懸空/未初始化的。 – Tim 2010-07-08 03:35:25

0

看我有類似的問題。 我的課程在BlackBerry的編譯器和qmake 4上運行良好,但在qtcreator 5(64和32b)上,我遇到了同樣的問題。 我追查到這 http://www.instructables.com/answers/Why-would-an-empty-stdmap-seg-fault-on-the-first/#CXBBGN4GQO92M2Q

看起來像默認的構造函數不會在某些編譯器上正確初始化。 我在父類構造函數上添加了一個clear(),現在似乎工作。

它也可能發生,如果你有一些靜態聲明(或更糟糕的外部)和地圖應該實例化的時間不是預期的。

我希望它有幫助。