Sign in to follow this  

[C++] Lifetime of Objects Allocated with new

This topic is 2818 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

I am writing a program to improve my C++ skills. It currently has a class that can have child classes of the same type (nesting is not limited). I was using array of pointers to store the child classes:
node::~node (void)
{
	for (unsigned int i = 0; i < nOfSubs; i++)
		delete sub[i];
	if (sub) {free (sub); sub = 0;}

	if (name) {free (name); name = 0;}
	if (cont) {free (cont); cont = 0;}
}
int node::addSub (wchar_t *name0, wchar_t *cont0, node **addedNode)
{
	sub = (node **) memGet (sub, (nOfSubs + 1) * sizeof (*sub)); //only hand made alloc:malloc (edit: malloc/realloc) switch funtion
	if (!sub)
		return -1;
	sub[nOfSubs] = new node; //note this line!!!
	if (sub[nOfSubs]->set (name0, cont0))
	{
		delete sub[nOfSubs];
		if (nOfSubs)
			sub = (node **) memGet (sub, nOfSubs * sizeof (*sub));
		else
		{
			free (sub);
			sub = 0;
		}
		return -1;
	}
	sub[nOfSubs]->sup = this;
	if (addedNode)
		*addedNode = sub[nOfSubs];
	nOfSubs++;
	return 0;
}

As you can see, I'm using "new" to spawn a new "node". Recently I found this page that suggests that my code should not work, but destructor (node::~node(void)) gets called when I use "delete". Does this work by luck and I'm up to a nasty surprise later or am I misunderstanding the principle of scoping? [Edited by - transistor09 on March 31, 2010 2:35:43 AM]

Share this post


Link to post
Share on other sites
A scope is what's between { and }. All the variables created in a scope are destroyed when leaving it, except for those created with the new operator.

So:

{
node n1;
node * n2 = new n2();
} // Here, the n1 destructor will be called, but not n2.

What the page you linked was saying is that when you create an object with new, you must keep its pointer somewhere to be able to call delete on it. For instance, in my example, there's a leak because the pointer on n2 is lost when leaving the scope and there's no way to delete.

I'm not sure to understand everything in the code you provided, but as long as you're creating the object in add and then deleting it in the destructor, it should be fine (unless you keep references to nodes that could be deleted somewhere else in you program).

I'm not sure if my explanation is clear enough.

Share this post


Link to post
Share on other sites
Quote:
Original post by Faelenor
Read the original post and maybe you'll find out...

Well, I guess he's referring to the MSDN documents, but I don't see anything wrong or confusing with them, maybe I'm missing something.

Share this post


Link to post
Share on other sites
Quote:
Original post by kloffy
Quote:
Original post by Faelenor
Read the original post and maybe you'll find out...

Well, I guess he's referring to the MSDN documents, but I don't see anything wrong or confusing with them, maybe I'm missing something.


You're not. The MSDN document is both clear and correct.

Share this post


Link to post
Share on other sites
Quote:
Original post by transistor09
Oh, right! The variable gets out of scope, not allocated memory! Way to be confusing, Microsoft!


It's not confusing at all:

Quote:
Objects allocated with the new operator are not destroyed when the scope in which they are defined is exited.


"Objects allocated" == "allocated memory". This doesn't go out of scope. The variable holding the pointer goes out of scope, because that's what variables normally do.

Quote:
On the other note, will this recursive destructor be a performance killer?


Well, was it a performance killer to create the nodes in the first place? 'delete' is thought of as faster than 'new', because 'delete' only has to tell the system "this memory is available again", while 'new' has to search for a piece of memory that's big enough. Regardless, it's work that has to be done anyway, so there is no point worrying about how fast it is. The only thing that's at all interesting about it is that you create the nodes one at a time and potentially destroy a bunch of them at once. But it's still not a big issue. Remember, even garbage-collected languages do a full collection over hundreds of megabytes of objects in some few milliseconds. (You can try to make a garbage-collector for C++, but they are not very robust, because the code can't know for sure what is a pointer and what isn't - there are lots of ways to 'hide' a pointer.)

Share this post


Link to post
Share on other sites
Quote:
Original post by ChaosEngine
You're not. The MSDN document is both clear and correct.

Sorry if my accusation was a bit harsh, I was just exploiting the stereotype.
Quote:
Original post by NumberXaero
If youre improving your C++ skills, then why are you mixing free() (and I assume malloc? in getMem) along with new and delete?

Um, there is an error in original post, I meant to say "malloc:realloc". The new/delete tigger constructor/destructor while malloc/realloc/free allows dynamic arrays without me needing to manually copy the memory. Is it bad anyway (even if I keep track of them and use the appropriate functions)?

Share this post


Link to post
Share on other sites
Quote:
Original post by transistor09
Um, there is an error in original post, I meant to say "malloc:realloc". The new/delete tigger constructor/destructor while malloc/realloc/free allows dynamic arrays without me needing to manually copy the memory. Is it bad anyway (even if I keep track of them and use the appropriate functions)?


It's error-prone and you don't see it very often, so it might hurt some programmers' eyes. A morally appropriate solution would be using ::std::vector<> to take care of memory management.

Share this post


Link to post
Share on other sites
Quote:
Original post by ComicSansMS
It's error-prone...

It's inside a class. Fixed once--fixed forever, right? Although it would be a bad habit.
Quote:
Original post by ComicSansMS
... and you don't see it very often, so it might hurt some programmers' eyes.

Ok, You got me, I'm a crappy programmer...
Quote:
Original post by ComicSansMS
A morally appropriate solution would be using ::std::vector<> to take care of memory management.

What about constructor/destructor? If vector doesn't do that the code would still be mixed.

Share this post


Link to post
Share on other sites
Quote:
Original post by transistor09
What about constructor/destructor? If vector doesn't do that the code would still be mixed.


not sure what you mean here.

one way to solve this would be to add a ::std::vector<node> class member that will store all nodes maintained by the class. the class can be queried to give pointers/iterators to node objects in that vector. upon destruction, the destructor of ::std::vector is called automatically and will free all nodes it contains. no more worrying about destruction for you [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by ComicSansMS
one way to solve this would be to add a ::std::vector<node> class member that will store all nodes maintained by the class. the class can be queried to give pointers/iterators to node objects in that vector. upon destruction, the destructor of ::std::vector is called automatically and will free all nodes it contains. no more worrying about destruction for you [smile]

That sounds nice. I'm going to investigate std::vector some more in next project. Right now my "nodes" work fine for me.

Share this post


Link to post
Share on other sites
Quote:
Original post by transistor09
What about constructor/destructor? If vector doesn't do that the code would still be mixed.


Malloc allocates memory. New constructs an object. The two operations are not interchangeable.

Of an object needs to be constructed, its constructor needs to be invoked. If it needs a constructor, it probably needs a destructor and a copy and/or move operator set. These things allow a good programmer to provide strong guarantees about behaviour through the use of class invariants.

The std::vector container constructs and destroys the objects it holds. Many objects have trivial constructors or destructors, so it can be like malloc/free if necessary. Pointers are objects with trivial construct/destroy semantics, but because of their usage (eg. possibly pointing to other objects ofdynamic duration) you may be better off storing smart pointers in a vector.

Share this post


Link to post
Share on other sites

This topic is 2818 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.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this