Помогите понять segfault с помощью std :: map / boost :: unordered_map - PullRequest
2 голосов
/ 08 июля 2010

У меня есть некоторый код для управления ресурсами (изображениями, шрифтами, сетками и т. Д.) С использованием статического класса шаблона, позволяющего клиентскому коду делать что-то вроде:

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"Тип "должен иметь конструктор, принимающий 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;

_resources относится к типу table_t.

Проблема с boost::unordered_map Я получаю segfault при вызове на find (происходящем из find_iterator).Однако вместо std::map я либо получаю ошибку в операции вставки (начиная с _Rb_tree_decrement), либо при вызове find (начиная с string::compare).

Проблема возникает только в 2-й раз, когда запрашивается ресурс (fileName действителен при возникновении сбоя).

Поскольку это происходит как с map, так и с unordered_map IЯ предполагаю, что я должен делать что-то странное, чтобы вызвать это, какие-то идеи?

Спасибо.

РЕДАКТИРОВАТЬ: Все еще проблема, я был неправ, что это происходит только во 2-й раз ресурсзапрашиваетсяОднако первые 2 вызова для получения ресурса успешны, это 3-й вызов, который вызывает segfault (каждый вызов для другого ресурса).

Вот трассировка стека:

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

Ответы [ 3 ]

2 голосов
/ 08 июля 2010

Я не могу заметить никаких явных ошибок, вы пробовали Valgrind (при условии, что вы используете какую-то * nix систему)?Это бесценный инструмент для поиска ошибок памяти, и похоже, что это может быть один из них.

0 голосов
/ 11 июля 2014

Смотри, у меня была похожая проблема. Мой класс отлично работал на компиляторе BlackBerry и qmake 4. но на qtcreator 5 (64 и 32b) у меня возникла та же проблема. я проследил это http://www.instructables.com/answers/Why-would-an-empty-stdmap-seg-fault-on-the-first/#CXBBGN4GQO92M2Q

похоже, что конструктор по умолчанию не инициализируется правильно на каком-то компиляторе. я добавил clear() в конструктор родительского класса и теперь, кажется, работает.

Это также может произойти, если у вас есть статические объявления (или, что еще хуже, extern) и время, когда должна быть создана карта, не является ожидаемым.

Надеюсь, это поможет.

0 голосов
/ 08 июля 2010

Проблема возникает только при втором запросе ресурса

Это наводит меня на мысль, что ваш код может освобождать ресурс - в первый раз все нормально, затем вы освобождаете его, затем в следующий раз, когда контейнер пытается получить доступ к этой памяти, он вызывает ошибки.

...