Search code examples
cocos2d-xcocos2d-x-3.0

(cocos2d-x 3.1 + VS2012) TextureCache::addImageAsync causes a crash occasionally


I load some textures in asynchronously at the beginning of my game, about 40-50 of them.

vector<string> textureFileNames;
textureFileNames.push_back("textures/particle.png");
textureFileNames.push_back("textures/menu_title.png");
...
textureFileNames.push_back("textures/timer_bar.png");
for (auto fileName: textureFileNames)
{
    Director::getInstance()->getTextureCache()
            ->addImageAsync(fileName, CC_CALLBACK_1(LoadingLayer::textureLoadedCallback, this));
}

My textureLoadedCallback method does nothing funky; at this stage it simply increments a value and updates a progress timer. The callback is called from the main thread by cocos2d-x design, so I don't suspect any problems arise from there.

90% of the time this works fine. But sometimes it crashes in VS2012 midway through loading the textures:

Debug Assertion Failed!

Program: C:\Windows\system32\MSVCP110D.dll
File: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\vector
Line: 1140

Expression: vector subscript out of range

Breaking at this point, I can see that it dies in the internals of vector, specifically the [] operator, and traces back through _Hash to the TextureCache::loadImage() method: auto it = _textures.find(asyncStruct->filename) on line 174 of CCTextureCache.cpp. _textures is defined as std::unordered_map<std::string, Texture2D*> _textures, a standard library unordered map. asyncStruct->filename resolves to the full path and filename of a texture to load.

Using the debugger, I can see that the filename is fine. I can see that _textures already contains the 19 textures before this one that it has processed just fine.

The fact that it seems to just be dying in the midst of the standard library doesn't strike me as right... but I'm unable to determine where CCTextureCache goes wrong. Only that it doesn't always fail, and that it's failing in an asynchronous thread. There's no concurrency bollocks going on with my code (as far as I know).

Is this a cocos2d-x bug, a VS2012 bug or a bug with my code I pasted above?


Solution

  • I think a potential cause could be that the for loop issues like 19 async image loads all at once, which may or may not be supported by that method. Try issuing the next async load only after your texture callback is called. That way no two async loads are performed simultaneously.