Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Game works fine in debug target but not in release target.

Credits go to Edgar Reynaldo for helping out!
This thread is locked; no one can reply to it. rss feed Print
Game works fine in debug target but not in release target.
tariel36
Member #14,214
April 2012

Hello!

I've got some strange issue here. For some time I make game with Allegro 5.0.9 in CodeBlocks with SEPARATLY downloaded MinGW (the most recent version I belive, coz downloaded it few days ago). So my code compiles and works fine in debug-target, from both CB-side and windows-side. I decided to try it out in release-target today, and here comes the problem. For some reason, it crashes as release-target, doesn't matter if run from CB or directly from windows. My researches showed me it crashes somewhere around drawing or bitmap operations inside my engine class (outside it, ex. in main() it works fine, atleast loading bmp, drawing bmp and fliping display). I'm pretty sure all modules and resources are loaded and initialized, otherwise my app would close itself before any crash could occur.

I mentioned it crashes in my engine class, so it's important (i think so) to mention that's a singleton, and most of code is inside of it (Around 650 lines of code with my formatting). I managed to "find" 2 crash reasons (couldn't go any futher).

First occurs when I try to add object to vector, where object contains ALLEGRO_BITMAP * in constructor, ex.:

#SelectExpand
1CButton::CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, const std::string str, ALLEGRO_BITMAP * image) : 2 PosX(px), PosY(py), Width(px+w), Height(py+h), Color(c), Text(str), Image(image) 3{}

and then somewhere

#SelectExpand
1Buttons.push_back(CButton(272,256,256,40,WHITE,"some txt",RESOURCES.GetBitmap("Button_256x40"))); //Buttons is a vector

And that crash throws

#SelectExpand
1terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc

in console or just crashes. (I found out that bad_alloc is thrown when I try to push_back no more than 2 buttons).

And if I comment out that vector, it just crashes on

#SelectExpand
1al_clear_to_color(al_map_rgb(0,200,255)); // even on al_clear_to_color() ! 2al_draw_textf(RESOURCES.GetTTF_Font("OSP-DIN"), al_map_rgb(255,0,0),400,200,ALLEGRO_ALIGN_CENTER,"MAINMENU");

but it never crashed on

#SelectExpand

I know it's hard to guess with such small ammount of information, but maybe anyone have an idea what's wrong?

I'm sorry for not including source code to topic, but I'm not sure where the problem is, so i would have to upload whole 15xx lines, but if someone needs it I can do so. But I warn you, that you'll get a headache coz of how much it sucks. ;D

Thanks in advance.

Additional info:
RESOURCES is #define from CResource::GetInstance(), where CResource is another singleton class which holds almost all resources (bitmaps, fonts, samples..).

"just crash" means that no info about error is thrown. It looks similar to
{"name":"conshost-croak.png","src":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/0\/004bb6ba9a65874887a00bc5d742dcff.png","w":532,"h":286,"tn":"\/\/djungxnpq2nug.cloudfront.net\/image\/cache\/0\/0\/004bb6ba9a65874887a00bc5d742dcff"}conshost-croak.png

And at last my linker settings:

#SelectExpand
1-s 2-static-libgcc 3-static-libstdc++ 4liballegro-5.0.9-monolith-static-mt.a 5libopenal-1.14-static-mt.a 6libvorbisfile-1.3.2-static-mt.a 7libvorbis-1.3.2-static-mt.a 8libdumb-0.9.3-static-mt.a 9libFLAC-1.2.1-static-mt.a 10libfreetype-2.4.8-static-mt.a 11libogg-1.2.1-static-mt.a 12libzlib-1.2.5-static-mt.a 13 14libgdiplus.a 15libuuid.a 16libkernel32.a 17libwinmm.a 18libpsapi.a 19libopengl32.a 20libglu32.a 21libuser32.a 22libcomdlg32.a 23libgdi32.a 24libshell32.a 25libole32.a 26libadvapi32.a 27libws2_32.a 28libshlwapi.a

Only diffrences between debug and release are that allegro libs got "-debug" more and there's no "-s" in debug-target

Edgar Reynaldo
Member #8,592
May 2007
avatar

If std::bad_alloc is being thrown, you are probably resizing or newing something with an unitialized variable for the size, which will be zeroed out in debug mode, but not release, hence the large size request. That's my guess. Use some try/catch blocks to isolate it.

tariel36
Member #14,214
April 2012

Thanks for reply. Since I couldn't really find anything with try and catch blocks (maybe I used them wrong) I created new project and started to copy parts of code to main.cpp. After couple of minutes I probably found the cancer that's killing my game, but that's really, really weird. I've copied only ~250 lines of code, mostly allegro and resources inits, button class, "main menu loop" and all includes and defines. The mean part of code is:
al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str());
Inside button draw() method. It's weird, because al_draw_textf() in main block works fine.
There's button class code, maybe I've done something wrong here?

#SelectExpand
1class CButton { 2private: 3 float PosX, PosY; 4 float Width, Height; 5 ALLEGRO_COLOR Color; 6 std::string Text; 7 ALLEGRO_BITMAP *Image; 8 9public: 10 CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, 11 const std::string str, ALLEGRO_BITMAP * image 12 ); 13 14 float GetPosX() const { return PosX; } 15 float GetPosY() const { return PosY; } 16 float GetWidth() const { return Width; } 17 float GetHeight() const { return Height; } 18 std::string GetText() const { return Text; } 19 20 void Draw(); 21}; 22 23CButton::CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, 24 const std::string str, ALLEGRO_BITMAP * image) : 25 PosX(px), PosY(py), Width(px+w), Height(py+h), Color(c), Text(str), Image(image) 26{} 27 28void CButton::Draw() { 29 if(Image == NULL) al_draw_filled_rectangle(PosX,PosY,Width,Height,Color); 30 else al_draw_bitmap(Image,PosX,PosY,0); 31 32 // The one here crashes the game (if not commented out) 33 //al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str()); 34}

OSP_DIN is a ttf font, but ttf addon start's without errors, and font, as I said, works in main().

Any ideas?:-X

Edgar Reynaldo
Member #8,592
May 2007
avatar

tariel36 said:

al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str());

You said this is crashing your program? OSP_DIN is probably returning an invalid font (because it was destroyed or is null). But you said the font works fine in main? Do you have any al_destroy_font's in your destructors? And in combination with that, do you make copies of any of your objects that contain ALLEGRO_FONT's? If you make a copy it will destroy your font when it goes out of scope, and cause your program to crash later on. If that is the case, you need to prohibit copying or implement a copy constructor.

Do you know how to get a backtrace when it crashes? Or is it still throwing bad_alloc?

tariel36
Member #14,214
April 2012

If al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str()); is present, indeed game crashes. I wrote line of code to check if OSP_DIN returns NULL, but it doesn't (atleast if(OSP_DIN == NULL) cout << "no font"; says so). Also there is no al_destroy_font() anywhere.

I'm not aware of any copy actions (maybe I missed something?).
I'm not sure if I know how to get backtrace, so let's say I dont know.
It doesn't thorw bad_alloc anymore.

I scrapped my code as much as I could, so you can see "whole" thing.

#SelectExpand
1#define ALLEGRO_STATICLINK 2 3#include <allegro5/allegro.h> 4#include <allegro5/allegro_image.h> 5#include <allegro5/allegro_primitives.h> 6#include <allegro5/allegro_font.h> 7#include <allegro5/allegro_ttf.h> 8 9#include <string> 10#include <iostream> 11#include <vector> 12 13#define BLACK al_map_rgb(0,0,0) 14#define WHITE al_map_rgb(255,255,255) 15#define GRAY al_map_rgb(166,166,166) 16 17using namespace std; 18 19ALLEGRO_DISPLAY *MainDisplay; 20ALLEGRO_TIMER *GameTimer; 21ALLEGRO_EVENT_QUEUE *GameEventQueue; 22const float FPS = 30; 23 24ALLEGRO_FONT * OSP_DIN; 25ALLEGRO_BITMAP * Button_256x40; 26 27class CButton { 28private: 29 float PosX, PosY; 30 float Width, Height; 31 ALLEGRO_COLOR Color; 32 std::string Text; 33 ALLEGRO_BITMAP *Image; 34 35public: 36 CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, 37 const std::string str, ALLEGRO_BITMAP * image 38 ); 39 ~CButton(); 40 41 void Draw(); 42}; 43 44CButton::CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, 45 const std::string str, ALLEGRO_BITMAP * image) : 46 PosX(px), PosY(py), Width(px+w), Height(py+h), Color(c), Text(str), Image(image) 47{} 48CButton::~CButton() {} 49 50void CButton::Draw() { 51 if(Image == NULL) al_draw_filled_rectangle(PosX,PosY,Width,Height,Color); 52 else al_draw_bitmap(Image,PosX,PosY,0); 53 54 if(OSP_DIN == NULL) cout << "no font\n"; 55 al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str()); 56} 57 58int main() { 59 60 if(!al_init()) return 1; 61 if(!al_init_image_addon()) return 2; 62 al_init_font_addon(); 63 if(!al_init_ttf_addon()) return 3; 64 if(!al_init_primitives_addon()) return 4; 65 66 if(!al_install_keyboard()) return 5; 67 if(!al_install_mouse()) return 6; 68 69 MainDisplay = al_create_display(800, 640); 70 if(!MainDisplay) return 7; 71 72 GameTimer = al_create_timer(1.0 / FPS); 73 if(!GameTimer) return 8; 74 75 GameEventQueue = al_create_event_queue(); 76 if(!GameEventQueue) return 9; 77 78 OSP_DIN = al_load_ttf_font("data/arial.ttf",18,0); 79 if(OSP_DIN == NULL) return 10; 80 81 Button_256x40 = al_load_bitmap("data/Button_256x40.png"); 82 if(Button_256x40 == NULL) return 11; 83 84 al_register_event_source(GameEventQueue, al_get_display_event_source(MainDisplay)); 85 al_register_event_source(GameEventQueue, al_get_timer_event_source(GameTimer)); 86 al_register_event_source(GameEventQueue, al_get_keyboard_event_source()); 87 al_register_event_source(GameEventQueue, al_get_mouse_event_source()); 88 89 bool redraw = true; 90 bool endd = false; 91 92 std::vector <CButton> Buttons; 93 94 Buttons.push_back(CButton(272,256,256,40,WHITE,"Nowa Gra",Button_256x40)); 95 Buttons.push_back(CButton(272,304,256,40,WHITE,"Load",Button_256x40)); 96 Buttons.push_back(CButton(272,352,256,40,WHITE,"HighScores",Button_256x40)); 97 Buttons.push_back(CButton(272,400,256,40,GRAY,"Options (NYI)",Button_256x40)); 98 Buttons.push_back(CButton(272,448,256,40,WHITE,"Exit",Button_256x40));; 99 100 while(!endd) { 101 ALLEGRO_EVENT ev; 102 al_wait_for_event(GameEventQueue, &ev); 103 104 if(ev.type == ALLEGRO_EVENT_TIMER) { 105 redraw = true; 106 } else if(ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) { 107 return 0; 108 } else if(ev.type == ALLEGRO_EVENT_MOUSE_BUTTON_UP) { 109 110 } else if(ev.type == ALLEGRO_EVENT_MOUSE_AXES) { 111 redraw = true; 112 } 113 114 if(redraw && al_is_event_queue_empty(GameEventQueue)) { 115 116 redraw = false; 117 al_clear_to_color(al_map_rgb(0,200,255)); 118 119 for(unsigned int i=0;i<Buttons.size();++i) Buttons[i].Draw(); 120 al_draw_textf(OSP_DIN, BLACK ,400,200,ALLEGRO_ALIGN_CENTER,"MAINMENU"); 121 122 al_flip_display(); 123 } 124 } 125 126 return 0; 127}

:-[

@edit
I tried to run release-target with debugger and breakpoints at lines 54 and 55 (in above code). It gave me:

#SelectExpand
1Child process PID: 2120 2Program received signal SIGSEGV, Segmentation fault. 3In ?? () () 4Continuing... 5Program received signal SIGSEGV, Segmentation fault. 6In ntdll!LdrQueryProcessModuleInformation () (C:\Windows\system32\ntdll.dll) 7Continuing... 8[Inferior 1 (process 2120) exited with code 030000000005] 9Debugger finished with status 0

I'm not sure if it's important, but since it gave SIGSEGV, i found it interesting and worth to mention.

Edgar Reynaldo
Member #8,592
May 2007
avatar

I compiled your code and used placeholder fonts and graphics and it worked fine for me in both release and debug mode, static link and dynamic.

Some logic errors I found :

tariel36 said:

#SelectExpand
1CButton::CButton(const float px, const float py, const float w, const float h, const ALLEGRO_COLOR c, 2 const std::string str, ALLEGRO_BITMAP * image) :
3 PosX(px), PosY(py), Width(px+w), Height(py+h), Color(c), Text(str), Image(image)
4{} 5 6 7//.... 8 9 10void CButton::Draw() { 11 if(Image == NULL) al_draw_filled_rectangle(PosX,PosY,Width,Height,Color); 12 else al_draw_bitmap(Image,PosX,PosY,0); 13 14 if(OSP_DIN == NULL) cout << "no font\n";
15 al_draw_textf(OSP_DIN,BLACK, PosX, PosY, ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str());
16}

The first highlighted line is incorrect because you are assigning width and height of the button to (px + w) and (py + h) which are the right and bottom edges respectively, not the width and height. The second line is wrong because you're centering the text on the left edge of the button.

As to why it is crashing for you, I'm not sure. You may be mixing library versions somehow but I don't know.

tariel36
Member #14,214
April 2012

When you said it works for you and about mixing versions, something poked me to check gcc version again. Guess what. It was not 4.7 ... >.< I have chosen "use pre-packed repository" instead of "download latest repository" during first installation, probably. I tried to compile both main and test projects after update, both worked. Thanks a lot for your time and patience.

I am really sorry for wasting so much of your time because of such stupid mistake. :-[

About highlightened lines. I know that those are not real width and height, but when I call button constructor I just put the width and height for button, so naming it like that, seemed logic, to me atleast.

#SelectExpand
1//button will be 256px long and 40px high. Constructor takes care of math. 2CButton(272,256,256,40,WHITE,"Nowa Gra",Button_256x40));

Also I removed real text positioning for testing purposes, the real one looks like that:

#SelectExpand
1al_draw_textf(OSP_DIN,BLACK, PosX+((Width-PosX)/2), PosY+((Height-PosY)/2)-(al_get_font_line_height(OSP_DIN)/2), ALLEGRO_ALIGN_CENTRE,"%s",Text.c_str());

Go to: