Help understanding segfault with std::map/boost::unordered_map
I have some code to handle resource (images, fonts, mesh data, etc.) management using a template'd static class, allowing client code to do something like:
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();
The "resource type" must have a constructor taking a const std::string&
.
getResource
is implemented as follows:
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
is defined as typedef typename boost::unordered_map< std::string, boost::shared_ptr<ResourceType> > table_t;
_resources
is of type table_t
.
The problem is with boost::unordered_map
I get a segfault on the call to find
(originating from find_iterator
). However, with std::map
instead, I either get a segfault on the insert operation (originating from _Rb_tree_decrement
), or on the call to find
(originating from string::compare
).
The problem only occurs the 2nd time a resource is requested (fileName is valid when the failure occurs).
As this is happening with both map
and unordered_map
I'm assuming I must be doing something bizarre somewhere to cause this, any ideas?
Thanks.
EDIT: Still having the problem, I was wrong about it only happening the 2nd time a resource is requested. However, the first 2 calls to get a resource are successful, it's the 3rd call that is causing the segfault (each call is for a differ开发者_JAVA技巧ent resource).
Here is a stack trace:
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
I can't spot any obvious errors, have you tried Valgrind (assuming you run some kind of *nix system)? It's an invaluable tool for finding memory errors, and this looks like it might be one of those.
The problem only occurs the 2nd time a resource is requested
This suggests to me that your code might be freeing the resource - the first time it's all fine, then you free it, then the next time the container tries to access that memory, it segfaults.
Look i was having a similar problem. My class worked great on BlackBerry's compiler and qmake 4. but on qtcreator 5 (64 and 32b) i was having the same issue. i traced this http://www.instructables.com/answers/Why-would-an-empty-stdmap-seg-fault-on-the-first/#CXBBGN4GQO92M2Q
looks like the default constructor doesn't initialize correctly on some compiler.
i added a clear()
on the parent class constructor and now seems to work.
It also can happen if you have some static declarations (or worse extern) and the time in when the map should be instantiated is not the expected.
i hope it helps.
精彩评论