• Advertisement
Sign in to follow this  

C++ Class Destructor not working

This topic is 3735 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Ok here’s the story, I finished a demo for my game, but I noticed that the stand-alone exe got an error message when I close out of it so I decided to check out my class destructors. I did that by including iostream and adding a std::cout<<Destructing ship class<<std::endl; line at the end of the destructor. I don’t know the official name for this type of program but my program runs with the windows command prompt thingy behind it and it displays my cout messages. Anyways, the destructor message never shows, but my similar constructor messages show. How can I fix this? The classes are declared at the top of my main file (not in a function) so does that stop the destructor from running? And this is a real problem because my destructors are supposed to clean up the files I loaded. *gasp* Have I been leaking memory for the past 6 months! If you need to see some code just tell me because I don’t know what I could give you to help.

Share this post


Link to post
Share on other sites
Advertisement
The destructor should be called when the object is destroyed or out of scope. If it goes out of scope when the program ends the program might be closing before you cans see the destructor message. Code would certainly help to see what going on.

Share this post


Link to post
Share on other sites
The command line stays up even when the program closes and I have to close that separately by clicking the little 'x' so I think that it would show it if I used a destructor.

What code would you like? The actual destructor?


Ship::~Ship()
{
if(!surface)
{
SDL_FreeSurface(surface);
}
if(!altsurface)
{
SDL_FreeSurface(altsurface);
}
if(!explosionsurface)
{
SDL_FreeSurface(explosionsurface);
}
std::cout<<"Destroying a ship"<<std::endl;
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Booger
The command line stays up even when the program closes and I have to close that separately by clicking the little 'x' so I think that it would show it if I used a destructor.

What code would you like? The actual destructor?

*** Source Snippet Removed ***


My guess would be that the error is happening before the output line in the destructor. Take a closer look at the conditional statements around each SDL_FreeSurface call. You might want to invert those if statements. Right now it will only try to free a surface if it == 0 (NULL).

If any of those surface pointers is still NULL, when you attempt to free it the program will crash.

Also, the surface pointers that need to be freed will not be freed, and you will still be leaking memory. (The leaked memory will be taken care of as soon as the program closes anyway, but still.)


Ship::~Ship()
{
std::cout << "Entering Ship destructor." << std::endl; // The extra line of output will tell you if the program crashes between this line and the bottom line of the constructor.
if(surface)
{
SDL_FreeSurface(surface);
}
if(altsurface)
{
SDL_FreeSurface(altsurface);
}
if(explosionsurface)
{
SDL_FreeSurface(explosionsurface);
}
std::cout << "Exiting Ship destructor." << std::endl;
}


Share this post


Link to post
Share on other sites
Ok I understand what you were saying about my surface pointers, but it still doesn't work, and the first line doesn't even show up.

Share this post


Link to post
Share on other sites
Quote:

What code would you like? The actual destructor?

The context where the ship object is constructed/deleted.

Does the ship object inherit a base class that does not have a virtual destructor?
Could it be that the ship instance you are deleting is contained/referenced by a object/singleton that is already deleted?

Share this post


Link to post
Share on other sites
Well pulpfist, I have an "enemyship" class that is derived from my "ship" class.

And the classes are declared outside of any functions so I'm not sure about their context of their deletion.

Share this post


Link to post
Share on other sites
When is SDL_Quit() being called? You probably shouldn't call any SDL functions after this point. If it is being called by atexit you should be very careful, as Im not sure whether global destructors are called before or after atexit functions.

In any case the best solution is not to have these objects as globals anyway, you can probably make them local to main without a huge amount of work.

Finally, a direct quote from the SDL doc wiki:
Quote:
It is safe to pass NULL as surface, in which case SDL_FreeSurface will do nothing.

Share this post


Link to post
Share on other sites
Quote:
Original post by Evil Booger
Well pulpfist, I have an "enemyship" class that is derived from my "ship" class.


if your Ship destructor is not declared virtual you will be leaking then (depending a little on how you call things... but it really should be virtual)

Share this post


Link to post
Share on other sites
@Captain P
Quote:

Can you post the code where you create instances of these classes?

Sure.

Ship Player1(Round(GAME_SCREEN_WIDTH/2,SHIP_SPEED),GAME_SCREEN_HEIGHT-SPRITE_SIZE);



That code is at the top of my main.cpp file and the constructor simply takes values for the initial position of the ship.


EnemyShip Grunt(20,SCREEN_HEIGHT-GAME_SCREEN_HEIGHT);
EnemyShip Zapper(200,SCREEN_HEIGHT-GAME_SCREEN_HEIGHT);



That code is at the end of my enemyship.h header file.

@rip-off
But i have a function that loads the surfaces for the ships, if I localize the ships to the main function, will the load_files() function still be able to load them?

@rollo
Ok I added virtual to the beginning of my destructor for the ship class. But it still doesn’t show the text.

Share this post


Link to post
Share on other sites
well if I understand what you are saying your enemyships are global. that means that their destructors is called sometime when the main functions returns and the program ends.

One thing that comes to mind is that your Ship destructors is called after you have called SDL_Quit.

EnemyShip Grunt, Zapper;

int main(...)
{
Ship Player1;

...
SDL_Quit(...);

// Player1 destructor gets called, but SDL subsystems is already closed so SDL_FreeSurface may crash
// enemyship destructors is called about here. Same problem as above...
}

Im not too familiar with SDL but I guess this could be the problem.

There is different ways to do this but one thing you can try

int main(...)
{
Ship *Player1 = new Ship(...);
EnemyShip *Grunt = new EnemyShip(...);
EnemyShip *Zapper = new EnemyShip(...);

...

// Force destruction of objects...
delete Zapper;
delete Grunt;
delete Player1;

// close SDL
SDL_Quit(...);
}

This way we know that the object destructors is called before SDL is closed down. Without seeing the code its hard to say exactly but that is something you could try in order to localize the problem.
From what you have said so far there is realy no reason to believe that the destructors is the problem.

edit:
If you have a global function (load_files) that need access to the objects, you can pass pointers/references to the objects as function arguments, or better yet give the Ship class a load_file member function.

Share this post


Link to post
Share on other sites
Quote:
Original post by pulpfist

int main(...)
{
Ship *Player1 = new Ship(...);
EnemyShip *Grunt = new EnemyShip(...);
EnemyShip *Zapper = new EnemyShip(...);

...

// Force destruction of objects...
delete Zapper;
delete Grunt;
delete Player1;

// close SDL
SDL_Quit(...);
}



Better still, use an anonymous inner scope:

int main(...)
{
{
Ship Player1(...);
EnemyShip Grunt(...);
EnemyShip Zapper(...);

...
} // all objects destroyed after here
// close SDL
SDL_Quit(...);
}




Quote:

But i have a function that loads the surfaces for the ships, if I localize the ships to the main function, will the load_files() function still be able to load them?


I have no idea [smile]. Since they used to be globals, you'll have to either pass the objects to the function as parameters (use references). However, have you considered allowing the objects to load their own files, much in the same way as they destroy them. You could add an additional string parameter to the constructor, and load the images from that file.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement