I whipped up a quick little program to test some ideas I have been thinking of, and was rather dismayed when it segfaults when closing.
The source:
1 | |
2 | int CFrame::LoadFrame(char *path, int ID) |
3 | { |
4 | bmpFrame = load_bmp(path,NULL); |
5 | intFrameID = id |
6 | |
7 | if(!bmpFrame) return 0; |
8 | |
9 | return 1; |
10 | } |
11 | |
12 | //not anywhere near completed yet |
13 | void CAnimation::LoadFrames() |
14 | { |
15 | if(!frameArray[0].LoadFrame("media/Walk1.bmp", 1)){allegro_message("ERROR |
16 | Loading Image"); } |
17 | if(!frameArray[1].LoadFrame("media/Walk2.bmp", 2)){allegro_message("ERROR |
18 | Loading Image"); } |
19 | } |
20 | |
21 | // --snip-- |
1 | int main() |
2 | { |
3 | allegro_init(); |
4 | install_keyboard(); |
5 | |
6 | set_color_depth(24); |
7 | set_gfx_mode(GFX_AUTODETECT_WINDOWED, 640,480,0,0); |
8 | |
9 | |
10 | |
11 | CAnimation Animation1; |
12 | |
13 | Animation1.LoadFrames(); |
14 | Animation1.clean(); |
15 | |
16 | readkey(); |
17 | |
18 | |
19 | return 1; |
20 | } |
21 | END_OF_MAIN() |
So all I essentially do is load two tiny sprites into an array (which works apparently). I do not draw them (yet), I just have them there. As soon as I press a key to leave, it segfaults.
I notice that if I change 'readkey()' to while(!key[KEY_ESC]){} the segfault seems to miraculously disappear.
Any reasons why?
bmpFrame is a BITMAP*?
And sorry, but I don't understand your CAnimation::LoadFrames() method:-/
Yeah, basically framesArray[] is an array of 'Frame', which has a BITMAP *bmpFrame; inside it.
edit:
So what the CAnimation::LoadFrames() does is load the frames with the required bitmaps. It's hardcoded and whatnot, but I was just testing out some ideas.
edit2:
I am using Windows XP Pro SP2 btw. Not sure if the OS would make a difference here...
Lets see CAnimation::clean().
Also, why return 1?
Lets see CAnimation::clean().
Also, why return 1?
Well, return 1; was changed from return 0; I was kind of flabergasted for a bit and started changing things to try and nail down the problem. That was actually why the whole 'clean()' methods were developed. CFrame has a clean method which basically checks to see if the bmpFrame is empty or not. If it is not empty then the bitmap is destroyed. CAnimation has a method of the same name which goes through each frame in it's frameArray calling the clean() method of each frame. The segfault was appearing before I added this, so I don't think it was relevant.
void CFrame::clean() { if(bmpFrame) destroy_bitmap(bmpFrame); } void CAnimation::clean() { int i=0; for(i;i<intNumFrames;i++) { frameArray<i>.clean(); } }
What I am doing is making an OOP animation system. There was a thread here about the whole thing.
Got destructor?
Got destructor?
Well, no. The clean() methods are supposed to mimic one. I remember using destroy_bitmap(blah) in destructors before and it caused segfaults when exiting as well.
When I destroy_bitmap(bVariable), I also set bVariable back to NULL, that way, if for some reason clean() is called after a previous clean(), it won't try to destroy bad data.
When I destroy_bitmap(bVariable), I also set bVariable back to NULL, that way, if for some reason clean() is called after a previous clean(), it won't try to destroy bad data.
I'll make a note to do that. I still would like to know what caused that segfault...
Is it still just caused by the readkey() function? Try commenting out other lines with the readkey() still there to see if it keeps segfaulting.
Well, when I commented out the loading of the images it did not crash. This confuses me because the images loaded fine as far as I can tell. I didn't actually draw them or even use them in any way.
I find it weird that when I uncomment the image loading and comment out the readkey() and replace with the conditional loop the problem disappears.
edit:
Perhaps these are the code demons my teacher was talking/joking about
Try not putting the class on the stack. Either make it global, or do:
CAnimation *Animation1 = new CAnimation; ... delete Animation1; return 0;
hmm after doing what you said to do Kitty Cat an 'Application Error' occurs.
I'll upload a picture of my error. It is different then before, because before I would get the whole send/don't send error report. I would also have to manually kill the process from task manager before I could recompile before. Now the process seems to be taken out automatically.
What is frameArray?
frameArray is an array of Frames
class CAnimation { private: CFrame frameArray[2]; //... }
What's intNumFramesset to? If it's uninitialized garbage, it's probably trying to clean more frames than are really there.
It's actually been initialized with a value of two... I do so in the LoadFrames() method.
Try leaving out the calls to shutdown allegro.
if(bmpFrame) destroy_bitmap(bmpFrame);
When will people realise that destroy_bitmap() deals fine with NULL?
And do set pointers to NULL after freeing them. It will prevent crashes from double frees or invalid pointer dereferences.
About your problem: make sure you don't call Allegro functions from global destructors (I didn't read the whole thread, so maybe this was proposed before).
Add printf's in your cleaning/destructing code to see how far it goes before segfaulting, that's the easiest way I know to fix those bugs.
When will people realise that destroy_bitmap() deals fine with NULL?
It does? In what way? if(!bmp) return; ?
destroy_bitmap(3) Allegro manual destroy_bitmap(3)
NAME
destroy_bitmap - Destroys any type of created bitmap. Allegro game pro-
gramming library.
SYNOPSIS
#include <allegro.h>
void destroy_bitmap(BITMAP *bitmap);
DESCRIPTION
Destroys a memory bitmap, sub-bitmap, video memory bitmap, or system
bitmap when you are finished with it. If you pass a NULL pointer this
function won't do anything. See above for the restrictions as to when
you are allowed to destroy the various types of bitmaps.
SEE ALSO
create_bitmap(3), load_bitmap(3)
Oops When was it added? I recall having my game crash on stuff like that back in the dark 4.0.2 era. Thanks for the info though!
Maybe it crashed freeing an unitialized BITMAP * that doesn't = NULL.