A newb question...why's the destructor called right after initialization

I’m still a new developer, and was doing some things with SDL in C, but
decided that C++ had some advantages over C. So I’ve been trying to get
this little snippet of code to do something, and have run into a
problem.
TrueMobile is a class. I create an instance of it called background,
and an SDL_Surface * gets initialized when I do so. It’s dimensions are
640x480.
What I can’t understand is why background’s destructor is called as
soon as it’s initialized. It makes using the class…troublesome at
best. I suppose I could go ahead and write a function outside the
constructor that initializes the surface, but it seems that avoids the
purpose of using a constructor in the first place.
Any ideas?

Thanks,
Austin

SOURCE___________

#ifndef ODDSOFT_ORG_SDL
#define ODDSOFT_ORG_SDL
#include<SDL/SDL.h>
#endif

#ifndef ODDSOFT_ORG_ORIENTATION
#define ODDSOFT_ORG_ORIENTATION
#include"include/orientation.h"
#endif

#ifndef ODDSOFT_ORG_TRUE_IMOBILE
#define ODDSOFT_ORG_TRUE_IMOBILE
#include “include/TrueImobile.h”
#endif

#ifndef ODDSOFT_ORG_IOSTREAM
#define ODDSOFT_ORG_IOSTREAM
#include
#endif

using namespace toehead;

int main()
{
atexit(SDL_Quit);

static SDL_Surface *screen;

if(SDL_Init(SDL_INIT_VIDEO != 0))
{
	std::cout << "Unable to init video: " << SDL_GetError() << "\n";
	return 1;
}

screen = SDL_SetVideoMode(640, 480, 16, SDL_DOUBLEBUF |

SDL_FULLSCREEN);
if(screen == NULL)
{
std::cout << "Unable to set video mode: " << SDL_GetError() << “\n”;
return 1;
}

TrueImobile background("bmp/BackGround.bmp");
std::cout << "Before background is used.\n";

background.drawSprite(screen);
std::cout << "After background is used.\n";

SDL_FreeSurface(screen);

return 0;

}

OUTPUT____________

frame->w = 640 frame->h = 480 // From Constructor
Destructor! // From Destructor
Before background is used. // From main
src.x = 0 src.y = 0 // From drawSprite
src.w = 59428 src.h = 0 // From drawSprite

dest.x = 0 dest.y = 0 // From drawSprite
dest.h = 480 dest.w = 640 // From drawSprite

Now frame->w = 4384804 // From drawSprite
Now frame->h = -1014956032 // From drawSprite
After background is used. // From main
Destructor! // Destructor

Hi.

There’s little we can do without seeing the code of TrueImobile. My guess
is that the object is copied, which causes a SDL_Surface* to get shared
between two instances. The first object to get destroyed destroys in turn
the surface. You have to forbid copying of TrueImobile and use raw or
smart pointers to manage objects of the class.

HTH,
BrunoOn Wed, 29 Dec 2004 22:13:30 -0500, Austin W. Dunham V wrote:

I’m still a new developer, and was doing some things with SDL in C, but
decided that C++ had some advantages over C. So I’ve been trying to get
this little snippet of code to do something, and have run into a
problem.
TrueMobile is a class. I create an instance of it called background,
and an SDL_Surface * gets initialized when I do so. It’s dimensions are
640x480.
What I can’t understand is why background’s destructor is called as
soon as it’s initialized. It makes using the class…troublesome at
best. I suppose I could go ahead and write a function outside the
constructor that initializes the surface, but it seems that avoids the
purpose of using a constructor in the first place.
Any ideas?

Thanks,
Austin

First of all, a couple of other things…

Quoth “Austin W. Dunham V” , on 2004-12-29 22:13:30 -0500:

#ifndef ODDSOFT_ORG_SDL
#define ODDSOFT_ORG_SDL
#include<SDL/SDL.h>
#endif

The portable way to do this is << #include “SDL.h” >>.

int main()

Last I recall, SDL’s main() renaming hack sometimes required that main
be declared as << int main(int argc, char *argv[]) >>.

static SDL_Surface *screen;

Why is this static?

if(SDL_Init(SDL_INIT_VIDEO != 0))

Do you mean << if (SDL_Init(SDL_INIT_VIDEO) != 0) >>?

SDL_FreeSurface(screen);

Don’t free the main video surface. See the SDL_SetVideoMode
documentation.

As for your original question, it may be helpful to see the source of
TrueImobile. Also, which compiler and operating system are in use
here?

—> Drake Wilson

-------------- next part --------------
A non-text attachment was scrubbed…
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20041229/3bcc2c15/attachment.pgp

[…]

TrueImobile background(“bmp/BackGround.bmp”);
std::cout << “Before background is used.\n”;

background.drawSprite(screen);
std::cout << “After background is used.\n”;

SDL_FreeSurface(screen);

return 0;
}
[…]

I don’t see what the problem is… You create ‘background’; a local
(stack) instance of class TrueImobile. Then you use it, and finally
the main() function ends, and ‘background’ is destroyed as a result
of going out of scope.

Seems to be working just fine, that is, so I assume you weren’t aware
that C++ actually creates instances (not pointers) if you tell it
to - even on the stack. :slight_smile:

(Object Pascal does not, for example. It always creates pointers,
resulting in a syntax inconcistency that I find rather annoying and
confusing. C and C++ just do what you say, whereas Object Pascal does
what the designers (think) you mean… hehe)

Oh, and never free SDL’s display surface! (I’m surprised if you
don’t get a segfault when atexit() calls SDL_Quit() after that one.)

As to atexit(), it should do the trick, but I personally prefer to be
concistent and stick with explicit cleanup code in languages with
manual memory management. :slight_smile: (And it’s been suggested that atexit()
isn’t all that reliable anyway…)

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Thursday 30 December 2004 04.13, Austin W. Dunham V wrote:

For a fist attempt at doing something with C++ for years, I got a
little ambitious. I’ll probably start over making this much simpler to
start with, but here it is: TrueImobile is included below.
One of my main goals was creating a Sprite that would pretty much keep
track of itself. There’s MasterSprite, an abstract class with the bare
minimum of information, and a couple subclasses for immobile and mobile
classes to build on top of.
Most of the work is done in the constructor, with drawSprite blitting
frame to whatever surface you tell it to.
What’s odd is that background’s destructor, in main, is called before I
can even call background.drawSprite()…

    TrueImobile background("bmp/BackGround.bmp");
    std::cout << "Before background is used.\n";

The destructor get's called between the line that initializes

background and printing the before line…

I've made up a mock couple of classes, and it's not exhibiting the same

behavior. I’ll let you know if I find the mistake myself.

Thanks again,
Austin

// TrueImobile.h

/******************************************************************

  • The Imobile Class for non moving sprites.

*****************************************************************/

#ifndef ODDSOFT_ORG_SDL
#define ODDSOFT_ORG_SDL
#include <SDL/SDL.h>
#endif

#ifndef ODDSOFT_ORG_ORIENTATION
#define ODDSOFT_ORG_ORIENTATION
#include “orientation.h”
#endif

#ifndef ODDSOFT_ORG_IMOBILE
#include “Imobile.h”
#define ODDSOFT_ORG_IMOBILE
#endif

namespace toehead
{

class TrueImobile : public Imobile
{

/****************************************************************
*

  • These are the members from the parent class.

protected:
int x, y; // Position of upper left corner.
int w, h; // Width and height of the sprite.
int curr_orientation;
int vissible; // Is sprite vissible
SDL_Surface *frame; // Actual frame.

*****************************************************************/

public:

void setPosition(int x, int y);
void setHeightWidth(int w, int h);
void setVissible(bool);
void setFrame(SDL_Surface *frame);
void setOrientation(int orientation);

int * getPosition();
int * getHeightWidth();
int getCurrOrientation();
bool getVissible();
SDL_Surface * getFrame();

void drawSprite(SDL_Surface *destination_surface);

TrueImobile();

TrueImobile(SDL_Surface *init_frame);

TrueImobile(char *load_file);

~TrueImobile();

};

}


// TrueImobile.cpp

#ifndef ODDSOFT_ORG_TRUE_IMOBILE
#define ODDSOFT_ORG_TRUE_IMOBILE
#include “include/TrueImobile.h”
#endif

#ifndef ODDSOFT_ORG_IOSTREAM
#define ODDSOFT_ORG_STDIO
#include
#endif

#define TI TrueImobile

using namespace toehead;

void TI::setPosition(int setX, int setY)
{
}

void TI::setHeightWidth(int setW, int setH)
{
}

void TI::setVissible(bool setV)
{
}

int * TI::getPosition()
{
int *rtrn;
return rtrn;
}

int * TI::getHeightWidth()
{
int *rtrn;
return rtrn;
}

bool TI::getVissible()
{
return true;
}

SDL_Surface * TI::getFrame()
{
return frame;
}

void TI::setFrame(SDL_Surface *new_frame)
{
frame = new_frame;
}

void TI::drawSprite(SDL_Surface *destination_surface)
{
src.x = src.y = 0;
src.h = frame->h;
src.w = frame->w;
dest.x = dest.y = 0;
dest.h = destination_surface->h;
dest.w = destination_surface->w;

std::cout << "src.x = " << src.x << " src.y = " << src.y << "\nsrc.w =

" << src.w << " src.h = " << src.h << “\n\n”;
std::cout << “dest.x = " << dest.x << " dest.y = " << dest.y <<
”\ndest.h = " << dest.h << " dest.w = " << dest.w << “\n”;

std::cout << "\n\n\nNow frame->w = " << frame->w << "\nNow frame->h = "

<< frame->h << “\n”;

SDL_BlitSurface(frame, &src, destination_surface, &dest);
SDL_Delay(3000);

}

TI::TrueImobile()
{
}

TI::TrueImobile(SDL_Surface *init_frame)
{
SDL_Surface *temp;
temp=init_frame;
frame = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);

if(frame == NULL)
{
	std::cout << "Unable to load frame: " << SDL_GetError() << "\n";
}

std::cout << "frame->w = " << frame->w << " frame->h = " << frame->h <<

“\n”;
}

TI::TrueImobile(char *load_file)
{
TrueImobile( (SDL_Surface *)SDL_LoadBMP(load_file) );
}

TI::~TrueImobile()
{
std::cout << “Destructor!\n”;
}

Sorry, missed the most critical detail! :smiley:

[…]

frame->w = 640 frame->h = 480 // From Constructor

Destructor! // From Destructor

So that’s the instant destructor call…

My first though: Why is there only one message from the constructor,
when there are two messages from the destructor?

As others have pointed out, we need to see the source of TrueImobile
(the constructor, at least) to figure out what’s going on here.

[…]

Destructor! // Destructor

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Thursday 30 December 2004 04.13, Austin W. Dunham V wrote:

TI::TrueImobile(SDL_Surface *init_frame)
{
SDL_Surface *temp;
temp=init_frame;
frame = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);

if(frame == NULL)
{
std::cout << "Unable to load frame: " << SDL_GetError() << “\n”;
}

std::cout << “frame->w = " << frame->w << " frame->h = " << frame->h <<
”\n";
}

TI::TrueImobile(char *load_file)
{
TrueImobile( (SDL_Surface *)SDL_LoadBMP(load_file) );
}

This is the problem. In C++, on e constructor can’t call another. What
you are doing is constructing a second TrueImobile. What you want to do
can be done moving the code of the TrueImobile(SDL_Surface *init_frame) to
a private init() method and calling it from both constructors.

Bruno

[…]

TI::TrueImobile(SDL_Surface *init_frame)
{
SDL_Surface *temp;
temp=init_frame;
frame = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);

if(frame == NULL)
{
std::cout << "Unable to load frame: " << SDL_GetError() << “\n”;
}

std::cout << "frame->w = " << frame->w << " frame->h = " <<
frame->h << “\n”;
}

TI::TrueImobile(char *load_file)
{
TrueImobile( (SDL_Surface *)SDL_LoadBMP(load_file) );
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

There it is! :slight_smile: This constructor creates a temporary instance using
the other constructor, and then that instance is instantly thrown
away - and this instance is actually left uninitialized at that…

//David Olofson - Programmer, Composer, Open Source Advocate

.- Audiality -----------------------------------------------.
| Free/Open Source audio engine for games and multimedia. |
| MIDI, modular synthesis, real time effects, scripting,… |
`-----------------------------------> http://audiality.org -’
http://olofson.nethttp://www.reologica.se —On Thursday 30 December 2004 04.43, Austin W. Dunham V wrote:

Bruno,
Thanks for your input. I’ll fix that, and a few other things mentioned
to me, and all should be good.

AustinOn Wed, 2004-12-29 at 22:51, Bruno Mart?nez Aguerre wrote:

TI::TrueImobile(SDL_Surface *init_frame)
{
SDL_Surface *temp;
temp=init_frame;
frame = SDL_DisplayFormat(temp);
SDL_FreeSurface(temp);

if(frame == NULL)
{
  std::cout << "Unable to load frame: " << SDL_GetError() << "\n";
}

std::cout << "frame->w = " << frame->w << " frame->h = " << frame->h <<

“\n”;
}

TI::TrueImobile(char *load_file)
{
TrueImobile( (SDL_Surface *)SDL_LoadBMP(load_file) );
}

This is the problem. In C++, on e constructor can’t call another. What
you are doing is constructing a second TrueImobile. What you want to do
can be done moving the code of the TrueImobile(SDL_Surface *init_frame) to
a private init() method and calling it from both constructors.

Bruno


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

All,
It works now! Thanks one and all for your responses, they were spot
on.

Austin

David Olofson wrote:

Oh, and never free SDL’s display surface! (I’m surprised if you
don’t get a segfault when atexit() calls SDL_Quit() after that one.)

There’s a very simple reason why you don’t get a segfault - right at the start of SDL_FreeSurface:

if ((surface == NULL) ||
    (current_video &&
    ((surface == SDL_ShadowSurface)||(surface == SDL_VideoSurface)))) {
	return;
}

This doesn’t make it a good idea to free the display surface, but it does mean that you don’t have to work to avoid it.

Chris E.
-------------- next part --------------
A non-text attachment was scrubbed…
Name: signature.asc
Type: application/pgp-signature
Size: 252 bytes
Desc: OpenPGP digital signature
URL: http://lists.libsdl.org/pipermail/sdl-libsdl.org/attachments/20041231/f0b00a29/attachment.pgp