noob question - destructors - freeing memory...

S

someone

Hi

See this (stolen from the internet):

----------------------------------------
#include <iostream>
using namespace std;

class Base
{
public:
Base(){ cout<<"Constructing Base"<<endl;}

// this is a destructor:
virtual ~Base(){ cout<<"Destroying Base"<<endl;}
};

class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive"<<endl;}
~Derive(){ cout<<"Destroying Derive"<<endl;}
};

int main()
{
Base *basePtr = new Derive();
// delete basePtr; // <<<======== !! ! ! ! ! NB !!
return 0;
}

----------------------------------------

See middle line of main():

delete basePtr; // <<<======== !! ! ! ! ! NB !!


If I enable (uncomment) middle line, I get:
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base


If I disable (comment out) middle line, I get:
Constructing Base
Constructing Derive


========

This, I didn't quite expect, because I thought that at the end of the
program, all destructors where guaranteed to be called...

In my case, I have a longer program and I allocate memory with one of my
constructors, hence it is crucial to free the memory, but since the
virtual destructor is never called, I never free the memory...

In addition: In my full program (not shown here), I instantiate my new
object like:

int main(...)
{
...
Derive d1();
return 0; // or exit(1); if something went wrong somewhere
}

Is it required that I do, like in the example above:

int main(...)
{
...
Base *myPtr = new Derive();
delete myPtr;
return 0; // or exit(1); if something went wrong somewhere
}

???????

But what if my code does an exit(1) somewhere, which it could do at
least a dozens of times, in different parts of the program?


Please advice, thank you!
 
M

MikeWhy

someone said:
Hi

See this (stolen from the internet):

----------------------------------------
#include <iostream>
using namespace std;

class Base
{
public:
Base(){ cout<<"Constructing Base"<<endl;}

// this is a destructor:
virtual ~Base(){ cout<<"Destroying Base"<<endl;}
};

class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive"<<endl;}
~Derive(){ cout<<"Destroying Derive"<<endl;}
};

int main()
{
Base *basePtr = new Derive();
// delete basePtr; // <<<======== !! ! ! ! ! NB !!
return 0;
}

----------------------------------------

See middle line of main():

delete basePtr; // <<<======== !! ! ! ! ! NB !!


If I enable (uncomment) middle line, I get:
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base


If I disable (comment out) middle line, I get:
Constructing Base
Constructing Derive


========

This, I didn't quite expect, because I thought that at the end of the
program, all destructors where guaranteed to be called...

If pointers had destructors, what action should they take?
In my case, I have a longer program and I allocate memory with one of
my constructors, hence it is crucial to free the memory, but since the
virtual destructor is never called, I never free the memory...

In addition: In my full program (not shown here), I instantiate my new
object like:

int main(...)
{
...
Derive d1();
return 0; // or exit(1); if something went wrong somewhere
}

Is it required that I do, like in the example above:

int main(...)
{
...
Base *myPtr = new Derive();

foo(); // insert this line. See below.
delete myPtr;
return 0; // or exit(1); if something went wrong somewhere
}

???????
Yes.


But what if my code does an exit(1) somewhere, which it could do at
least a dozens of times, in different parts of the program?

exit() is a function call. In your final example above, if foo() called
exit(1), will your destructor be called? Given what you saw earlier, how
does exit() trigger process termination?

If instead of calling exit(), foo() throws an uncaught exception. How does
the program behave?

Calling exit() is a very bad idea. Ditto for terminating threads, only more
so. A simple return will suffice. Find some other mechanism to trigger
process (and thread) termination.
 
S

someone

If pointers had destructors, what action should they take?

Delete themselves? But not before they've destructed the objects they're
pointing to! After they've destructed (free'd) the dereferenced objects,
the pointers can free themselves...

Why doesn't that happen in the example in my post and in my full code?
foo(); // insert this line. See below.

Yes.

Ok, but I don't understand why... I found this post:
http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html

from where I qoute: "Static objects are deleted (so the destructor is
called) when global variables are deallocated, so when the program exits."

I believe this code:

int main(...)
{
...
Derive d1();
return 0; // or exit(1); if something went wrong somewhere
}

Has d1 to be a static object, hence when the program exits, the
destructor of d1 should be called just before exitting... Why don't this
happen?
exit() is a function call. In your final example above, if foo() called
exit(1), will your destructor be called? Given what you saw earlier, how
does exit() trigger process termination?

exit() is not a normal function call. Normally, code execution continues
right after the function calls. But not with exit(). Code below exit()
is not executed.
If instead of calling exit(), foo() throws an uncaught exception. How
does the program behave?

I later found some posts on google, suggesting to throw/catch
exceptions, however I'm not very good at using exceptions and fear that
the code will be much more complicated.
Calling exit() is a very bad idea. Ditto for terminating threads, only
more so. A simple return will suffice. Find some other mechanism to
trigger process (and thread) termination.

return() has exactly the same problem as exit: The code below return()
in main is not executed, hence I believe that exit() is some kind of
acronym for return() (from the main thread)...

Anyway, please explain why the static destructor is not called on exit.
I don't understand why not...
 
M

MikeWhy

someone said:
Delete themselves? But not before they've destructed the objects
they're pointing to! After they've destructed (free'd) the
dereferenced objects, the pointers can free themselves...

Why doesn't that happen in the example in my post and in my full code?


Ok, but I don't understand why... I found this post:
http://www.tech-archive.net/Archive/VC/microsoft.public.vc.mfc/2007-05/msg01433.html

from where I qoute: "Static objects are deleted (so the destructor is
called) when global variables are deallocated, so when the program
exits."
I believe this code:

int main(...)
{
...
Derive d1();
return 0; // or exit(1); if something went wrong somewhere
}

Has d1 to be a static object, hence when the program exits, the
destructor of d1 should be called just before exitting... Why don't
this happen?


exit() is not a normal function call. Normally, code execution
continues right after the function calls. But not with exit(). Code
below exit() is not executed.


I later found some posts on google, suggesting to throw/catch
exceptions, however I'm not very good at using exceptions and fear
that the code will be much more complicated.


return() has exactly the same problem as exit: The code below return()
in main is not executed, hence I believe that exit() is some kind of
acronym for return() (from the main thread)...

return is a C/C++ keyword. exit() is a function call. It kills the process
and does not return. Since exit() doesn't return, foo() doesn't return.
Since foo() doesn't return, execution will not continue in main(). Your
delete will not be called.

You're asking the right questions. You now need to understand the
distinction.

There also was a reason to bring up exceptions. The exception would have
behaved as you thought exit() might. In the contexts you describe -- calling
exit(1) in multiple locations -- the semantics and behavior are as you
expected from exit().

Anyway, please explain why the static destructor is not called on
exit. I don't understand why not...

The truth of the matter is that pointers do not have destructors. My
intention was not to lead you astray, however. You'll visit this again in
shared_ptr and auto_ptr classes.
 
G

Garrett Hartshaw

Hi

See this (stolen from the internet):

----------------------------------------
#include <iostream>
using namespace std;

class Base
{
public:
Base(){ cout<<"Constructing Base"<<endl;}

// this is a destructor:
virtual ~Base(){ cout<<"Destroying Base"<<endl;}
};

class Derive: public Base
{
public:
Derive(){ cout<<"Constructing Derive"<<endl;}
~Derive(){ cout<<"Destroying Derive"<<endl;}
};

int main()
{
Base *basePtr = new Derive();
// delete basePtr; // <<<======== !! ! ! ! ! NB !!
return 0;
}



See middle line of main():

delete basePtr; // <<<======== !! ! ! ! ! NB !!



If I enable (uncomment) middle line, I get:
Constructing Base
Constructing Derive
Destroying Derive
Destroying Base



If I disable (comment out) middle line, I get:
Constructing Base
Constructing Derive





This, I didn't quite expect, because I thought that at the end of the
program, all destructors where guaranteed to be called...

In my case, I have a longer program and I allocate memory with one of my
constructors, hence it is crucial to free the memory, but since the
virtual destructor is never called, I never free the memory...

In addition: In my full program (not shown here), I instantiate my new
object like:

int main(...)
{
...
Derive d1();
return 0; // or exit(1); if something went wrong somewhere
}

Is it required that I do, like in the example above:

int main(...)
{
...
Base *myPtr = new Derive();
delete myPtr;
return 0; // or exit(1); if something went wrong somewhere
}



But what if my code does an exit(1) somewhere, which it could do at
least a dozens of times, in different parts of the program?



Please advice, thank you!

A statically constructed object will be destroyed when the scope is
left.

e.g destructors will be called in:
int main()
{
Derived d;
return 0;
}

A dynamically constructed object (created using new) is destroyed
when delete is called.

e.g destructors called in this:
int main()
{
Base * b = new Derived();
delete b;
return 0;
}

but not this:
int main()
{
Base * b = new Derived();
return 0;
}


When exit(int) is called, the program is terminated *without
unwinding the stack* so no destructors are called.

When a execption is thrown and not caught, the program is terminated
*with stack unwinding*, so static objects are destroyed.

Note:
int main()
{
Base * b = new Derived();
throw std::exception();
delete b;
return 0;
}

In the above, the delete expression is never reached, so destructors
are not called.
If this is an issue, a smart pointer (boost::shared_ptr,
boost::scoped_ptr, etc:) should be used.
 
S

someone


No answer?
return is a C/C++ keyword. exit() is a function call. It kills the
process and does not return. Since exit() doesn't return, foo() doesn't
return. Since foo() doesn't return, execution will not continue in
main(). Your delete will not be called.

But it's not the answer to why, when I create static objects, the
destructor of d1 is not called when exitting... Right?
You're asking the right questions. You now need to understand the
distinction.

There also was a reason to bring up exceptions. The exception would have
behaved as you thought exit() might. In the contexts you describe --
calling exit(1) in multiple locations -- the semantics and behavior are
as you expected from exit().



The truth of the matter is that pointers do not have destructors. My
intention was not to lead you astray, however. You'll visit this again
in shared_ptr and auto_ptr classes.

So you don't want to explain it?

FYI: I have no shared_ptr and auto_ptr classes, I don't know what it
means and I'll never take them. I'm too old for that. You're not that
old yourself and hence assumed that everyone in here is a student, doing
school work? Never heard of something like: Went out of school years
ago, but am learning a new programming language anyway?

I don't understand why you not just explain it, instead of all this
irrelevant talk about if pointers have destructors and "you'll learn
that when you've taking the same courses in school like myself, son"?

The exception throw/catch-talk however, was relevant, thank you for that.

I don't see many explations to the static destructor-thing yet...
 
M

MikeWhy

someone said:
No answer?

Answered below in that message.
But it's not the answer to why, when I create static objects, the
destructor of d1 is not called when exitting... Right?


So you don't want to explain it?

I'll go so far as to say that pointers -- along with int, char, and arrays
as further examples -- do not have destructors. Plain old data, POD, as
opposed to classes and structs. To say more would needlessly repeat
countless books, articles, blogs, and archived usenet and chatboard
postings. From your well reasoned earlier post, it did seem to me all you
needed was a well directed nudge.

To answer your question, then... What would happen in your first example,
where you passed an int* to a function, if pointers had the behavior of
deleting their pointee in their hypothetical destructor?

I am still of the opinion that you need only a nudge, not a silver spoon. If
that wasn't the case, I assure you I would not be spending my time.

FYI: I have no shared_ptr and auto_ptr classes, I don't know what it
means and I'll never take them. I'm too old for that. You're not that
old yourself and hence assumed that everyone in here is a student,
doing school work? Never heard of something like: Went out of school
years ago, but am learning a new programming language anyway?

I don't understand why you not just explain it, instead of all this
irrelevant talk about if pointers have destructors and "you'll learn
that when you've taking the same courses in school like myself, son"?

The exception throw/catch-talk however, was relevant, thank you for
that.
I don't see many explations to the static destructor-thing yet...

It would please me if the explanation came next from you. It's entirely
likely, or at least possible, that I've been out of school as long as you.
 
S

someone

A statically constructed object will be destroyed when the scope is left.

e.g destructors will be called in:
int main()
{
Derived d;
return 0;
}

Ah, stupid me. I thought I had tried the above, and that it didn't work
- thank you very much. My mistake, maybe also in reply to MikeWhy...
A dynamically constructed object (created using new) is destroyed when
delete is called.

e.g destructors called in this:
int main()
{
Base * b = new Derived();
delete b;
return 0;
}

but not this:
int main()
{
Base * b = new Derived();
return 0;
}

Yes, this is clear now, the static thing was a brain-something that hit
me...
When exit(int) is called, the program is terminated *without unwinding
the stack* so no destructors are called.

Yes, clear.
When a execption is thrown and not caught, the program is terminated
*with stack unwinding*, so static objects are destroyed.

Aah, only static objects... DAMN...
Note: int main()
{
Base * b = new Derived();
throw std::exception();
delete b;
return 0;
}

In the above, the delete expression is never reached, so destructors are
not called.

That is a big problem/issue in my program, I think...

So if I allocate memory in my constructor, and I never call the
destructor and I keep running and exiting, running and exiting the
program, then I end up using all my memory because I never free'd it?
If this is an issue, a smart pointer (boost::shared_ptr,
boost::scoped_ptr, etc:) should be used.

Ooh, damn...

I hoped, I could avoid having to learn something new and timeconsuming
like boost...

Isn't there an easier solution without including more libraries?


Thank you very much, by the way!
 
M

MikeWhy

Hmmm...

#include <memory>

You may discount my earlier post. I had not understood our communications to
have been so severely crossed.
 
S

someone

Are these shared_ptr and auto_ptr relevant for solving the problem? I
googled it, but not sure if they solve anything...
It would please me if the explanation came next from you. It's entirely
likely, or at least possible, that I've been out of school as long as you.

Ok, good. Thank you very much.

I made a mistake, that confused me - I thought that the static
destructor wasn't called, when main() returned with a 0... It confused
me, don't know where I got that from...

Everything is ok, I asked some questions to Garret about how to fix my
problem now, hopefully without using boost::shared_ptr,
boost::scoped_ptr, etc.

hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
exit(num), that does try and catch everytime I risk the program
otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....
 
M

MikeWhy

someone said:
Are these shared_ptr and auto_ptr relevant for solving the problem? I
googled it, but not sure if they solve anything...

They don't directly address your problem. Strictly speaking, I felt the
problem was not simply that delete was not being called. The problem
entirely was that execution did not flow as you expected. auto_ptr was
relevant because it makes real that hypothetical deletion behavior
mentioned.
hmmmmmmmmmmmmmmmmmm. Maybe a quick solution is to #define a macro
exit(num), that does try and catch everytime I risk the program
otherwise would be calling exit(1) etc... hmmmmmmmmmmmmm....

It might be a good way to finish out your test program, which I understand
to be a study of object lifetimes and program flow. I would not have chosen
to introduce auto_ptr so early, but as it turns out, the role it plays is an
important part of the broader topic of exception-safety.

As a final note, hiding throw in a macro for exit is a bad idea. Blindly
replacing exit(1) with throw(1) might not be altogether unreasonable,
though.
 
S

someone

It might be a good way to finish out your test program, which I
understand to be a study of object lifetimes and program flow. I would

The test program is finished. It's posted here in the thread. The other
program is a big complicated program, where I have to find a solution,
to the problem where the destructor is not called, when exit(1) and/or
exceptions are thrown...
not have chosen to introduce auto_ptr so early, but as it turns out, the
role it plays is an important part of the broader topic of
exception-safety.

As a final note, hiding throw in a macro for exit is a bad idea. Blindly
replacing exit(1) with throw(1) might not be altogether unreasonable,
though.

Still don't solve the cleanup ("delete" / "free"ing up used memory
space) problem... Not sure what to do then...
 
L

LR

someone said:
That is a big problem/issue in my program, I think...

So if I allocate memory in my constructor, and I never call the
destructor and I keep running and exiting, running and exiting the
program, then I end up using all my memory because I never free'd it?

May I ask why you're allocating memory? I mean why are you writing new
explicitly in your code? What are you trying to do?
Ooh, damn...

I hoped, I could avoid having to learn something new and timeconsuming
like boost...

Isn't there an easier solution without including more libraries?

What compiler and version are you using? You may find what you need in
a header that shipped with your compiler.
 
S

someone

May I ask why you're allocating memory? I mean why are you writing new
explicitly in your code? What are you trying to do?

Because:

I have some graphical objects that should be displayed on the screen.
When I instantiate these objects, I don't know how many coordinates
there are. When I know it, I use new to allocate memory for x,y and
z-coordinates. It's pretty lame, if I should not allocate memory
dynamically... It's hard to believe, it is so cumbersome. It would also
look bad if I separate the x,y and z-coordinates from the graphical
objects themselves. And even that would not solve the
call-the-destructor-problem to free memory.
What compiler and version are you using? You may find what you need in
a header that shipped with your compiler.

1) g++ (Ubuntu/Linaro 4.6.1-9ubuntu3) 4.6.1
Copyright (C) 2011 Free Software Foundation, Inc.

and

2) Visual studio 2011

= (crossplatform)
 
J

Juha Nieminen

someone said:
This, I didn't quite expect, because I thought that at the end of the
program, all destructors where guaranteed to be called...

C++ does not implement garbage collection, which means that if you
allocate an object dynamically with 'new', you'll have to destroy it
explicitly with 'delete'. (Yes, I know that sucks, but either live with
it or switch to C#.)

If you want the dynamically allocated object to be destroyed automatically
you'll have to use a smart pointer like std::shared_ptr to handle it. In
most cases, though, it's better to avoid the 'new' if you can, and instead
handle objects by value. When an object is handled by value it will be
scope-bound, and thus will be destroyed when its scope ends. In surprisingly
many cases (especially to people accustomed to languages like Java or C#),
you don't need 'new' to handle objects.
 
N

Nick Keighley

not sure exactlywhat you're up to here. But

- hiding standard libraries behind macros seems like a bad idea.
For a start it makes reading your code very difficult for other
people.

- what do you mean "a macro [...] that catches everything"?
(slightly paraphrashing you)

As the other poster said calling exit() in a C++ is generally a bad
idea. It certainly precludes destrutors being called. I think the
effect you want could be had by throwing and not catching. This will
bubble all the way upto the top of the program, calling all the
relevent DTORs on the way. Then exiting.
The test program is finished. It's posted here in the thread. The other
program is a big complicated program, where I have to find a solution,
to the problem where the destructor is not called, when exit(1) and/or
exceptions are thrown...

there's something seriuslywrong if they aren't being called when
exceptions are thown!
Still don't solve the cleanup ("delete" / "free"ing up used memory
space) problem... Not sure what to do then...

post a simple, working program that illustrates your problem.
 
N

Nick Keighley

Ah, stupid me. I thought I had tried the above, and that it didn't work
- thank you very much. My mistake, maybe also in reply to MikeWhy...








Yes, this is clear now, the static thing was a brain-something that hit
me...


Yes, clear.


Aah, only static objects... DAMN...



That is a big problem/issue in my program, I think...

So if I allocate memory in my constructor, and I never call the
destructor and I keep running and exiting, running and exiting the
program, then I end up using all my memory because I never free'd it?


Ooh, damn...

I hoped, I could avoid having to learn something new and timeconsuming
like boost...

Isn't there an easier solution without including more libraries?

std::auto_ptr

though I believe this is now deprecated. Hasn't been removed though
and does the job.
 
N

Nick Keighley

On 12/31/2011 07:07 AM, LR wrote:


Because:

I have some graphical objects that should be displayed on the screen.
When I instantiate these objects, I don't know how many coordinates
there are. When I know it, I use new to allocate memory for x,y and
z-coordinates. It's pretty lame, if I should not allocate memory
dynamically... It's hard to believe, it is so cumbersome.

would std::vector solve your problem? Something like this:-

// vec.cpp

#include <vector>

struct Point
{
int x;
int y;
int z;
};

void draw (std::vector<Point>& graphicalObject)
{
// do whatever has to be done to draw the object
}

// make an object with pointCount points
void makeObject (int pointCount)
{
std::vector<Point> graphicalObject(pointCount);
// initialise it somehow
draw (graphicalObject);
// graphicalObject and all its points destroyed here
}

int main ()
{
int n = 10; // determine number of points somehow
makeObject (n);
}

<snip>
 
B

Bo Persson

someone said:
========

This, I didn't quite expect, because I thought that at the end of
the program, all destructors where guaranteed to be called...

In my case, I have a longer program and I allocate memory with one
of my constructors, hence it is crucial to free the memory, but
since the virtual destructor is never called, I never free the
memory...
In addition: In my full program (not shown here), I instantiate my
new object like:

int main(...)
{
...
Derived d1();
return 0; // or exit(1); if something went wrong somewhere
}

This actually doesn't create an object, but declares a function d1
that returns a Derived object. If you compare

Derived d1();

to the more common

int f();

you will see the similarity!


Bo Persson
 
B

Bo Persson

someone said:
Delete themselves? But not before they've destructed the objects
they're pointing to! After they've destructed (free'd) the
dereferenced objects, the pointers can free themselves...

Why doesn't that happen in the example in my post and in my full
code?

There are several reasons. One is that pointers are inherited from the
C language, and are expected to behave the same as they did there. In
C there are no destructors at all.

Another reason is that there can be several pointers pointing to the
same object. How are they supposed to know which one should delete the
object pointed to? Or if anyone should do that. Not all pointed-to
objects are created by new.

{
int i = 0;
int* p = &i;
}

Here we should definitely *not* call delete p.


Bo Persson
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top