making sure that the deallocated dynamically memory returns to the heap?

M

Marcus Kwok

Marcus said:
Now, deleting a pointer twice *can* be indicative of a logic error but
is not dangerous in and of itself; in fact if you set your pointer to 0
it can't even happen short of an overload of delete. If attempting to
delete the pointer twice is the only thing that goes wrong then who
cares?

Deleting a pointer twice is UB [FAQ 16.2].

Which only further emphasizes my point. Nothing says the program has
to crash or do anything remotely obvious or immediate.

Nothing says your program will operate correctly after that point
either.

Deleting pointers twice: Just Say "No"!
 
D

Daniel T.

Double deletion errors hide themselves quite well already. I would
prefer they didn't bring down the software when they happen.

Well, I prefer a crash that shows me that there is an error (and in a
debugger even where it is). After all, an error that you might not see is
still an error and can bite back later when you don't expect it.[/QUOTE]

Want to make sure you never have double deletion errors? Set the pointer
to NULL after the delete.

"delete p; delete p;" is a double deletion, "delete p; p = NULL; delete
p;" is NOT a double deletion...
 
R

Rolf Magnus

Daniel said:
Well, I prefer a crash that shows me that there is an error (and in a
debugger even where it is). After all, an error that you might not see is
still an error and can bite back later when you don't expect it.

Want to make sure you never have double deletion errors? Set the pointer
to NULL after the delete.[/QUOTE]

No. This just treats a symptom, not the actual illness.
"delete p; delete p;" is a double deletion, "delete p; p = NULL; delete
p;" is NOT a double deletion...

Well, it is still a bug, no matter how you call it. After I delete an
object, I assume that it doesn't exist anymore. If you have another delete
at a late point for the same object, that often (not always) means there is
some problem in the code, because it assumes the object is still existing,
even though it already has been deleted.
 
R

Rolf Magnus

Bob said:

For the same reason you can't set it to 0: Because the pointer is const.
While I can't use it for the array that I just deleted, I should certainly
be able to allocate another array, set the pointer to point to that array
and use it. But only if it is not a const pointer.

Uhm, yes. We were talking about what you can and can't do with a _const_
pointer, so my answer was of couse also just about that.
 
S

Stephen Howe

eg.
//start
char * p = new char[1000];
..
...
delete [] p;
//end

The quesiton was..How will I be sure the deallocated memory is returned
to heap?

This question might be to do with exception safety, and what is really being
asked is, "how can I guarantee that delete [] p will be executed if an
exception occurs between new[] and delete[]?" Something like

char * p = new char[1000];
try
{

}
catch(...)
{
delete [] p;
throw;
}
delete [] p;

will guard against this but it is messy and better still would be to
re-write using vector<char> as that will make the try-catch(...) redundant.

Stephen Howe

Stephen Howe



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
D

Daniel T.

Rolf Magnus said:
Well, it is still a bug, no matter how you call it. After I delete an
object, I assume that it doesn't exist anymore. If you have another delete
at a late point for the same object, that often (not always) means there is
some problem in the code, because it assumes the object is still existing,
even though it already has been deleted.

Nonsense. The only time you are assuming that an object exists, is when
you dereference the pointer without first checking for null. 'delete'
always checks for null so it never assumes the object still exists.

"delete p; p = NULL; delete p;" has no bugs in it. "delete p; p = NULL;
*p;" has a bug... One that most debugging systems will catch.

By guarding against double deletion, you are guarding against the wrong
thing. What you need to guard against is dereference of a invalid
pointer.
 
B

Bjorn Reese

I answered make p = NULL.But again the interviewer was probably
expecting different answer as the debate went on thereafter...

The interviewer was probably thinking of exception-safety. If an
exception is thrown between the new and delete operations, then p
is not released.

There are several solutions. Which one is the best depends on the
exact details of the code in question.

1. Place the array on the stack rather than on the heap.
2. Use try-catch.
3. Use smart pointers.
 
R

ralatalo

Funny thing is that if you are looking at/for a trick question/answer.

Strickly speaking the heap is the default location for allocated
memory.
Strickly speaking New/Delete (malloc/free) do not remove or put memory
on the heap. They manage a Free List of memory that is available on
the Heap and if that is insufficient they request additional memory
from the Operating System to be placed on/in the Heap.

That said, the memory was never removed from the Heap (assuming it was
there to begin with) in which case there is nothing that needs to be
done to return the memory to the heap.

All of the above is applicable for the memory being returned to the
Free list.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

roberts.noah

Rolf said:
Bob said:
make p a "char*const" instead of "char*"

Why?

I imagine it's to avoid a situation like:

p = new char[1000];
++p;
delete [] p;

which is probably UB, since the address passed to delete[] is no longer
the address obtained from new[].

But then you cannot set p = 0 after the delete[], either.

Why would you want to set it to 0 anyway? In other situations, it might make
sense, but you can't let the pointer point to something else (i.e. you
can't allocate another array and let it point to that array) so you can't
use p after the deletion anyway.

You can certainly try. "p[22] = 'a';" or in the case of objects
p->whatever(). If p never leaves the scope of some small block then it
is of no concern, but any time the scope of p extends beyond then these
techniques are not viable; you need to be able to set that pointer to 0
so that it can be verified.
 
K

kanze

Maciej said:
(e-mail address removed) wrote:
I was asked a question in an interview..
Its related to dynamically allocated and deallocated memory.
eg.
//start
char * p = new char[1000];
..
...
delete [] p;
//end
The quesiton was..How will I be sure the deallocated memory
is returned to heap?

[...]
No, it doesn't make any difference as far as the memory block
itself is concerned.

Actually, that's implementation defined. In fact, in the
implementation I use most of the time in my private work (g++
with the Boehm collection, the operator delete() function
replaced with a no-op), it does make a difference.

I don't know why, but for some reason, I don't think that that's
the sort of answer the interviewer was looking for. (If I were
the interviewer, and the interviewee didn't start his answer
with something along the lines of "well, using the Boehm
collector...", I don't think I'd accept it either.)
The problem is that *nobody* really knows what the interviewer
might expect if he's asking such questions. :)

Quite:).

[...]
And, BTW, don't forget that new/delete is not only about
memory: there are also *objects* which are constructed and
destructed in this memory.

Except that given the way the question was formulated, one
rather imagines that the use of char here is intentional, to
ensure that this issue doesn't come into play.

--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Rolf Magnus

Stephen said:
This question might be to do with exception safety, and what is really
being asked is, "how can I guarantee that delete [] p will be executed if
an exception occurs between new[] and delete[]?" Something like

char * p = new char[1000];
try
{

}
catch(...)
{
delete [] p;
throw;
}
delete [] p;

will guard against this but it is messy and better still would be to
re-write using vector<char> as that will make the try-catch(...)
redundant.

Or - more general - use the RAII technique, i.e. let a class do the
allocation/deallocation automatically. This can be a smart pointer or
std::vector<char> or something similar.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

Rolf Magnus

Strickly speaking the heap is the default location for allocated
memory.

Strictly speaking, the word "heap" has another meaning in C++. What you are
talking about is called the free or dynamic storage.
Strickly speaking New/Delete (malloc/free) do not remove or put memory
on the heap. They manage a Free List of memory that is available on
the Heap and if that is insufficient they request additional memory
from the Operating System to be placed on/in the Heap.

This may be the case, or it may be not. The way how memory is handled by
new/delete or malloc/free depends on the target platform. Remember that
there are C++ compilers for architectures that don't even have an operating
system.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
B

Bob Hairgrove

you can't use p after the deletion anyway.

You can certainly try. "p[22] = 'a';" or in the case of objects
p->whatever(). If p never leaves the scope of some small block then it
is of no concern, but any time the scope of p extends beyond then these
techniques are not viable; you need to be able to set that pointer to 0
so that it can be verified.

You can *try* just about anything. But after "delete p;" it's always
undefined behavior to do what you suggest, regardless of what the
scope of p might be (see sec. 5.3.5, paragraph 4 of the standard).
 
E

Earl Purple

Rolf said:
Strictly speaking, the word "heap" has another meaning in C++. What you are
talking about is called the free or dynamic storage.

You can point that out to the interviewer as an afterthought, but my
answer in an interview would be first to ideally use vector[char] (or
even string) or a smart-pointer (but beware it can't be auto_ptr or
boost::shared_ptr which don't do delete[]) but without using those, to
use catch(...) { delete[] p; throw; } workaround.


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
S

Stephen Howe

Or - more general - use the RAII technique, i.e. let a class do the
allocation/deallocation automatically. This can be a smart pointer or
std::vector<char> or something similar.

Yes agreed. The try-catch solution is just plain ugly.
I still think OP's question had exception safety in mind.

Stephen Howe



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
C

Carl Barron

Earl Purple said:
Rolf said:
Strictly speaking, the word "heap" has another meaning in C++. What you are
talking about is called the free or dynamic storage.

You can point that out to the interviewer as an afterthought, but my
answer in an interview would be first to ideally use vector[char] (or
even string) or a smart-pointer (but beware it can't be auto_ptr or
boost::shared_ptr which don't do delete[]) but without using those, to
use catch(...) { delete[] p; throw; } workaround.
a boost or tr1 shared_ptr CAN call delete [] upon destruction.

struct array_deleter
{
template <class T> operator ()(T *p){delete [] p;}
};

boost::shared_ptr<char> p(new char[100],array_deleter());
although for a buffer I'd probably use std::vector<char> myself,
unless the shared semantics made sense or the copying process is too
slow with vector.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
E

Earl Purple

Carl said:
a boost or tr1 shared_ptr CAN call delete [] upon destruction.

struct array_deleter
{
template <class T> operator ()(T *p){delete [] p;}
};

boost::shared_ptr<char> p(new char[100],array_deleter());
although for a buffer I'd probably use std::vector<char> myself,
unless the shared semantics made sense or the copying process is too
slow with vector.

yes of course, and that's how my own shared_ptr works as it happens if
you want to delete arrays (and it's used in my portable_string class).

You can't specify a deleter with boost::scoped_ptr though (but there is
boost::scoped_array). With this particular case you'd probably want
scoped_array because you're not sharing with anything (albeit that
shared_ptr will work with your array_deleter).

And practically are you really going to write your functor here? (It
doesn't check for completeness and I'm not 100% sure boost will do that
for you with your own deleter, although on this occasion T is char).


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
 
R

roberts.noah

Bob said:
you can't use p after the deletion anyway.

You can certainly try. "p[22] = 'a';" or in the case of objects
p->whatever(). If p never leaves the scope of some small block then it
is of no concern, but any time the scope of p extends beyond then these
techniques are not viable; you need to be able to set that pointer to 0
so that it can be verified.

You can *try* just about anything. But after "delete p;" it's always
undefined behavior to do what you suggest, regardless of what the
scope of p might be (see sec. 5.3.5, paragraph 4 of the standard).

Not if p == 0.
 

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,780
Messages
2,569,608
Members
45,248
Latest member
MagdalenaB

Latest Threads

Top