Bug @ CCLabelBMFont (making Cocos2d-x apps lock up)

Well, this one was really hard to find :slight_smile: took me at most 5 hours to get to the point where I was about to pull out my hair!

Both the Cocos2d-x tests and my own little game would completely lock up when CCLabelBMFont was used. This did however only happen when I was NOT using the debug versions of the Cocos2d-x library and apps, which made the lockup hard to investigate because of the missing debugging information and inability to step through the code using the debugger. No stracktraces either, and I donā€™t have tools to inspect memory and program data, so thatā€™s why it was really hard. Running the non-debug version with the debugger would not help either, because the problem would not show up at those times.

After a while of putting in lots and lots of oldskool printfā€™s and MessageBoxes, I succeeded in pinpointing the location of the lockup, which happened to be in $cocos2d_root/cocos2dx/label_nodes/CCLabelBMFont.cpp

Inside this file, thereā€™s a method named parseConfigFile(const char*). This method is indirectly used by CCBitmapFontAtlas::bitmapFontAtlasWithString(ā€¦) to load the .fnt file. It does that using C functions, like memset, memcpy and strchr.

Iā€™m still not exactly sure why it happens, but it looks like the use of memset causes a bunch of too many characters to be deleted at certain times, causing the very last ā€˜ā€™ to be removed, causing ā€œleftSizeā€ to stay above a certain value and in turn causing the while-loop to keep running and never exit. Et voila, the program locks up because of this series of very unfortunate events :slight_smile:

The font files for my game are generated by the Hiero font generator and the programs were all compiled and executed on Windows Vista, using Visual Studio 2008 and standard program optimization (no agressive optimization settings). As of yet, I have no idea if this bug shows up on other platforms.

Iā€™ve fixed it in the attached patch. If you would like to see the bug in action before patching up the Git version, please ask and Iā€™ll whip up a small sample program that shows the bug in action.


CCLabelBMFont_lockup.patch.zip (1.2 KB)

Thanks for your fix! Too much debugging work!
I will dig more to find the reason of this bug. It did looks curious.
Honestly, I have a string-process-phobia since I became a programmer, :slight_smile:

One question more, which platform are you using? win32? iphone?

Heh, so do I :slight_smile: thatā€™s why I like to use C++ string functions instead of the C ones. Makes those kind of operations a little less scary :slight_smile: And on top of that, itā€™s very very hard (perhaps even impossible?) to stay inside a while-loop forever when using std::getline instead of doing the hard work to extract the lines yourself, so thatā€™s a nice bonus!

Iā€™m using win32, by the way.
Unfortunately no iPhone, Android or uPhone yet, but Iā€™ll try to get my system ready for some of those soon.

To help you, Iā€™ve also uploaded a sample program as an attachment to this post. Instructions are simple:

  • extract the archive, go to the Release.win32 directory and run the CocosFontBug app <ā€” it should lock up, because itā€™ll use the original unpatched CCLabelBMFont.cpp
  • remember to NOT run it through the debugger, because it will do some things with the memory (like clearing unitialized variables). You wonā€™t see the bug then.
  • rename libcocos2d_patched.dll to libcocos2d.dll to see the patched behavior (using the patch from my previous post). This should run fine.
  • if youā€™d like to recompile the app, youā€™ll have to modify the path for the Cocos2d-x library first.

Thanks! What a nice guy! The source will help us too much.

Nah, itā€™s actually just a template app with some mods to keep it small, sorry. The only thing you can learn from it is how to render fonts from a .fnt file, which is nice to know, but nothing you havenā€™t seen already in the ā€œtestsā€ program distributed along with Cocos2d-x :slight_smile:

Thanks for your contribution!

Because of some platform not support std::iotream,so function parseConfigFile use memset, memcpy and strchr instead.
Now I have use std::string implement the function.And the logic is very simple.

Thank you again

Awesome, thanks! Looks nice with the std::string implementation! And dā€™oh, I totally forgot the unsupported platform stuff for std::iostream. Sorry about that.

ps. Your English is fine, no need to worry about that :slight_smile: