Allegro.cc - Online Community

Allegro.cc Forums » Programming Questions » Problem destroying bitmaps objects a destructor

This thread is locked; no one can reply to it. rss feed Print
Problem destroying bitmaps objects a destructor
chex_5
Member #14,081
February 2012

Hello, could anyone shed some light on why I have this problem destroying bitmaps & text? When I place al_destroy_bitmap() or al_destroy_font() in a class destructor, my program crashes when I try to close it. I made a workaround where I created an "unload()" function before I actually destroy the object, but that seems a little excessive.

The objects are created using the following code

#SelectExpand
1class text { 2 private: 3 ALLEGRO_FONT* font; 4 public: 5 text(const char* fontFile, int size, flags=0) {font = al_create_font(fontFile, size, flags);} 6 ~text(); {//left blank or else the program will crash} 7} 8 9class sprite{ 10 private: 11 ALLEGRO_BITMAP* image; 12 public: 13 sprite(const char* bitmapFile) {image = al_load_bitmap(bitmapFile);} 14 ~sprite(); {//left blank or else the program will crash} 15}

These destructors cause the program to crash unless they're left blank

#SelectExpand
1text::~text() { 2 al_destroy_font(font); 3} 4 5sprite::~sprite() { 6 al_destroy_bitmap(image); 7}

And these are the unload functions that I have to call before destroying the object

#SelectExpand
1text::unload() { 2 al_destroy_font(font); 3} 4 5sprite::unload() { 6 al_destroy_bitmap(image); 7}

What also seems weird is that I cannot place the unload functions in the destructors either. Can anyone help me out?

Edgar Reynaldo
Member #8,592
May 2007
avatar

Uhm, no. Both of those do exactly the same things.

Potential cause 1 : You are making copies of your text or sprite objects. This only performs a shallow copy of the pointer holding the resource, and when they go out of scope they get destroyed. Then when the original goes out of scope, it tries to destroy the same resource a second time, which would crash.

Potential cause 2 : You haven't properly initialized the necessary addons, for the fonts or for the images, which means your load calls will return null, and then when they go out of scope they try to destroy a null pointer, which will crash.

Potential cause 3 : They just aren't loading properly, but you don't check so you wouldn't know.

So, first make sure your resources are loading properly, either through text output, or through exceptions, or whatever else makes you happy.

Second, make sure the addons are initialized.

Third, make sure you don't make copies by value of your text and sprite objects, or write a proper copy constructor.

chex_5
Member #14,081
February 2012

The code I posted was just pseudocode. I have all of the addons initialized, the fonts and bitmaps using each class load properly, but where I run into problems is when I place "al_destroy_font()" or "al_destroy_bitmap()" in the destructor. I also run into problems if I place the unload functions in the corresponding class destructor as well.
Otherwise, the code runs fine when each unload/al_destroy function is called independent of the destructor, but crashes if placed inside of it. I'll go ahead and post the actual code that I have:

#SelectExpand
1#ifndef TEXT_H 2#define TEXT_H 3 4class text { 5private: 6 ALLEGRO_FONT* font; 7 ALLEGRO_COLOR color; 8 ALLEGRO_USTR_INFO textInfo; 9 ALLEGRO_USTR* ustring; 10 int size; 11 float x; 12 float y; 13 14public: 15 text(); 16 ~text(); 17 18 void loadFont (const char* file, int fontSize, int allegroFlags = 0); 19 void unloadFont (); //MUST be called before the destructor! 20 float getPosX () const {return x;} 21 float getPosY () const {return y;} 22 int getSize () const {return size;} 23 ALLEGRO_COLOR getColor () const {return color;} 24 void setPos (float xPos, float yPos) {x = xPos; y = yPos;} 25 void setText (const char* textData); 26 void setColor (float r, float g, float b, float a); 27 void draw (int allegroFlags = 0); 28}; 29 30inline void text::draw(int allegroFlags) { 31 al_draw_ustr( font, color, x, y, allegroFlags, ustring); 32} 33 34inline void text::setText(const char* textData) { 35 al_ustr_free(ustring); 36 ustring = al_ref_cstr(&textInfo, textData); 37} 38 39#endif /* TEXT_H */

#SelectExpand
1#include "text.h" 2//addons have already been initialized in another file 3 4text::text() { 5 font = NULL; 6 ustring = NULL; 7 size = 0; 8 x = 0; 9 y = 0; 10 color.r = 0.0f; 11 color.g = 0.0f; 12 color.b = 0.0f; 13 color.a = 0.0f; 14} 15 16text::~text() { 17 //al_destroy_font(font); 18 al_ustr_free(ustring); 19} 20 21void text::loadFont(const char* file, int fontSize, int allegroFlags) { 22 unloadFont(); 23 size = fontSize; 24 25 //search for true-type fonts by looking at the last two characters of the file extension 26 std::string fileParser = file; 27 unsigned int sizeCounter = fileParser.size(); 28 //there should be support for *.ttf & *.otf-style fonts 29 if ( (fileParser[sizeCounter - 1] == 'f' && fileParser[sizeCounter - 2] == 't') 30 || (fileParser[sizeCounter - 1] == 'F' && fileParser[sizeCounter - 2] == 'T')) { 31 fileParser = "TTF"; 32 font = al_load_ttf_font(file, size, allegroFlags); 33 } 34 else { 35 fileParser = "Bitmap"; 36 font = al_load_font(file, size, allegroFlags); 37 } 38 39 if (font != NULL) { 40 LOG("Successfully loaded font:\n"); 41 LOG("\tFile:\t%s\n", file); 42 } 43 else { 44 LOG("WARNING: Could not load font:\n"); 45 LOG("\tFile:\t%s\n", file); 46 } 47 48 LOG("\tType:\t%s\n", fileParser.c_str()); 49} 50 51void text::setColor(float r, float g, float b, float a) { 52 color.r = r; 53 color.g = g; 54 color.b = b; 55 color.a = a; 56} 57 58void text::unloadFont() { 59 al_destroy_font(font); 60 al_ustr_free(ustring); 61 size = 0; 62 x = 0; 63 y = 0; 64 color.r = 0.0f; 65 color.g = 0.0f; 66 color.b = 0.0f; 67 color.a = 0.0f; 68}

Edgar Reynaldo
Member #8,592
May 2007
avatar

Well, if they're loading properly, and your 'unload' function works properly when you call it yourself, then you are probably destroying the same resource multiple times due to shallow copying.

Make your destructor log each destruction :

text::~text() {
  LOG("Destroying font %p..." , font);
  al_destroy_font(font);
  LOG("Destroying ustring %p..." , ustring);
  al_ustr_free(ustring);
}

See if the same address gets destroyed twice...

Or, just make a test copy constructor :

   text(const text& t) {LOG("text object shallow copied");}

chex_5
Member #14,081
February 2012

Thanks for the reply.
I tried adding a blank copy constructor and logged it, as well as the regular constructor and destructor, but it doesn't seem as though any extra copies are being created. I think I'm going to download the allegro source code to see what might be causing this issue behind the scenes.

Edgar Reynaldo
Member #8,592
May 2007
avatar

This is not a problem with Allegro, I can tell you that right now. If you call al_destroy_font in one function, that is the same thing as calling it in another function.

Fire up a debugger first, and get a backtrace of the stack when it crashes. That will be WAY easier than trying to find a bug in Allegro that isn't there....

Go to: