Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / November 2007

Tip: Looking for answers? Try searching our database.

delete []

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
George - 30 Oct 2007 08:04 GMT
Hello everyone,

I remembered delete[] is implemented through operator overloading, but I am
not quite clear.

Could anyone recommend some links about how delete[] is implemented so that
I can learn and refresh my memory? :-)

thanks in advance,
George
David Wilkinson - 30 Oct 2007 12:54 GMT
> Hello everyone,
>
[quoted text clipped - 3 lines]
> Could anyone recommend some links about how delete[] is implemented so that
> I can learn and refresh my memory? :-)

George:

delete [] calls the destructor of each of the elements in the array, and
then frees the memory. What else do you need to know?

Signature

David Wilkinson
Visual C++ MVP

George - 30 Oct 2007 13:59 GMT
Hi David,

My question is how default delete and delete[] are implemented? And how/why
default delete and delete[] works for any data types, for example, we have a
class Foo, even if we do not implement delete and delete[] operator in class
Foo, we still could use delete[] to free the memory of an array of Foo
instances.

Could you help to describe how delete[] works for any data type please?
There are some default base class or some default delete[] implementation in
std namespace?

regards,
George

> > Hello everyone,
> >
[quoted text clipped - 8 lines]
> delete [] calls the destructor of each of the elements in the array, and
> then frees the memory. What else do you need to know?
Ben Voigt [C++ MVP] - 30 Oct 2007 14:45 GMT
> Hi David,
>
[quoted text clipped - 11 lines]
> in
> std namespace?

Any type that doesn't provide its own definition of new and delete (and the
array variations) will use the ones belonging to the base class (if it has
them) or else defined in the global (just :: not ::global) namespace.

Many runtime libraries provide different definitions that may do debug
tracing of allocations, etc.

If you tell us what library you are using probably someone can tell you what
file has the default definition of ::operator[]

> regards,
> George
[quoted text clipped - 13 lines]
>> delete [] calls the destructor of each of the elements in the array, and
>> then frees the memory. What else do you need to know?
George - 31 Oct 2007 03:22 GMT
Thanks Ben!

I appreciate for your kindness on helping this. I am using Visual Studio
2005 and developing C++.

I want to learn,

1. how delete[] is implemented in my environment (I suspect std::delete[] is
used and it will call destructor of each element in the array)?
2. why if we use new[] to allocate memory, then use delete (other than
delete[]) will cause memory leak?
3. why there is a common delete[] which suits for all various types of
object (I ask this question because I always do not overload operator delete
in my class and delete[] always works)?

regards,
George

> > Hi David,
> >
[quoted text clipped - 39 lines]
> >> delete [] calls the destructor of each of the elements in the array, and
> >> then frees the memory. What else do you need to know?
David Wilkinson - 31 Oct 2007 12:47 GMT
> Thanks Ben!
>
[quoted text clipped - 10 lines]
> object (I ask this question because I always do not overload operator delete
> in my class and delete[] always works)?

George:

When you call delete [], the compiler knows both the type of the object
and the number of objects that were allocated. Thus it has all the
information it needs to call *all* the destructors and free the memory.
No overload of operator delete [] is required.

When you call plain delete, the required behavior is to call *one*
destructor and free the memory. If the memory was allocated with new [],
and the objects themselves contain allocated memory, that memory is
leaked for the objects beyond the first. It is possible, I think, that a
compiler could implement delete so that it worked like delete [], but
this is not required by the standard.

The C++ standard says that memory allocated with new must be freed with
delete, and memory allocated with new [] must be freed with delete [].
Anything else is undefined behavior.

Signature

David Wilkinson
Visual C++ MVP

Peter Oliphant - 31 Oct 2007 16:40 GMT
Can one also free up memory allocated my 'gcnew' manually, or if you will,
when one desires (in contrast to letting the gc pick when)? If so, what does
one use (I'm assuming delete and delete[] won't work)...

[==Peter==]

>> Thanks Ben!
>>
[quoted text clipped - 28 lines]
> delete, and memory allocated with new [] must be freed with delete [].
> Anything else is undefined behavior.
Carl Daniel [VC++ MVP] - 01 Nov 2007 03:33 GMT
> Can one also free up memory allocated my 'gcnew' manually, or if you
> will, when one desires (in contrast to letting the gc pick when)? If
> so, what does one use (I'm assuming delete and delete[] won't work)...

Basically, no.  You can call GC::Collect(), but it's rarely a good idea to
do so.

-cd
Peter Oliphant - 01 Nov 2007 18:31 GMT
Cool. Actually, kind of a relief. That means I must rely on the GC, so I
don't have to really worry about freeing up memory since basically I'm not
'allowed' to.

I truly feel GC was a necessary feature. Most of my old progrmas truly
suffered from trying to figure out when to delete stuff, since it is often
the case a particualr class instance has no idea if something else external
to it is also using the memory. I can think of scenarios where is almost
impossible.

The old solution use to be to just allocate all of memory and write one's
own memory allocator by portioning it out. That way one could be aware at
that level if anything was still referencing it, and more important, could
easily free up all allocated memory upon exit by just freeing up the big
block it initially allocated and then portioned out (i.e., no memory leaks
upon exit).

But that IS in affect GC, so it is good this is now available to users of VS
C++ without having to write it as custom layer...

[==Peter==]

>> Can one also free up memory allocated my 'gcnew' manually, or if you
>> will, when one desires (in contrast to letting the gc pick when)? If
[quoted text clipped - 4 lines]
>
> -cd
George - 01 Nov 2007 07:56 GMT
Thanks Dave,

Your reply is very helpful. I am wondering if we do not implement
(overwrite) delete and delete[] in our class, there should be a default
implementation of delete and delete[] for all data types -- including our own
data types (class).

If I am using Visual Studio 2005, where is the default implementation? In
some default namespace (e.g. std) or some global function or in some default
base class?

regards,
George

> > Thanks Ben!
> >
[quoted text clipped - 28 lines]
> delete, and memory allocated with new [] must be freed with delete [].
> Anything else is undefined behavior.
Ben Voigt [C++ MVP] - 01 Nov 2007 14:18 GMT
> Thanks Dave,
>
[quoted text clipped - 8 lines]
> default
> base class?

It is in the global namespace.  C++ does not have default namespaces.  C++
does not have default base classes.

If you are using the Microsoft C++ runtime library (you can replace this
independent of the compiler), then it can be found in:

C:\Program Files\Microsoft Visual Studio 8\VC\crt\src\delete2.cpp

which is compiled into MSVCRT80.dll or statically linked into your program
(I think the name is libcmt.lib), depending on your project options.
George - 02 Nov 2007 07:03 GMT
Hi Ben,

Global namespace you mean namespace std?

regards,
George

> > Thanks Dave,
> >
[quoted text clipped - 19 lines]
> which is compiled into MSVCRT80.dll or statically linked into your program
> (I think the name is libcmt.lib), depending on your project options.
SvenC - 02 Nov 2007 19:06 GMT
Hi George,

> Global namespace you mean namespace std?

No. If Ben would have wanted to say "namespace std", then he would have
written "namespace std". But he wrote global and meant global. In fact he
did specify that in his first answer. Please see the relevant part cited
here:

> any type that doesn't provide its own definition of new
> and delete (and the array variations) will use the ones
> belonging to the base class (if it has them) or else
> defined in the global (just :: not ::global) namespace.

The global namespace can be seen as the namespace without name. If you want
to address a symbol of the global namespace you can do that by prepending ::
before that symbol. If you e.g. put a function min in some header without
putting it into a namespace and in some code you include that header and
also use <algorithm> and put a "using namespace std;" in your code, both min
functions are available and you will need to either use ::min or std::min

BTW and OT: you ask so many C++ beginner level questions in different news
groups. Did you ever think about buying a book? You might find some here:
http://www.accu.org

There is also a C++ FAQ at: http://www.parashift.com/c++-faq-lite

--
SvenC
George - 03 Nov 2007 06:37 GMT
Thanks SvenC,

I have checked http://www.accu.org, it is a not a web site which sells books
with discount, right? :-)

regards,
George

> Hi George,
>
[quoted text clipped - 25 lines]
> --
> SvenC
Bo Persson - 03 Nov 2007 11:59 GMT
:: Thanks SvenC,
::
:: I have checked http://www.accu.org, it is a not a web site which
:: sells books with discount, right? :-)

No, it's not.

But if you look in the Book Reviews section, you will find lot's of
books reviewed by IT professionals and listed from Exceptionally good
to Just crap.

If you buy some books marked Highly Recommended, you just cannot go
wrong. The "discount" part is that you can avoid buying the books at
the bottom of the list!

Bo Persson
George - 03 Nov 2007 13:58 GMT
Thanks Bo Persson,

Your answer is very clear!

regards,
George

> :: Thanks SvenC,
> ::
[quoted text clipped - 12 lines]
>
> Bo Persson
SvenC - 03 Nov 2007 12:01 GMT
Hi George,

> I have checked http://www.accu.org, it is a not a web site which sells
> books
> with discount, right? :-)

No, it is a site with book reviews to help you decide which one to buy at
your favorite book store.
Just click on "Book reviews" and search for C++ and maybe some other words
of interest like STL or COM.

--
SvenC
George - 01 Nov 2007 08:22 GMT
Thanks Dave,

Your reply is very helpful. I am wondering if we do not implement
(overwrite) delete and delete[] in our class, there should be a default
implementation of delete and delete[] for all data types -- including our own
data types (class).

If I am using Visual Studio 2005, where is the default implementation? In
some default namespace (e.g. std) or some global function or in some default
base class?

regards,
George

> > Thanks Ben!
> >
[quoted text clipped - 28 lines]
> delete, and memory allocated with new [] must be freed with delete [].
> Anything else is undefined behavior.
Bo Persson - 31 Oct 2007 19:06 GMT
:: Thanks Ben!
::
[quoted text clipped - 6 lines]
:: std::delete[] is used and it will call destructor of each element
:: in the array)?

No, it is not std::delete[], it is actually two different parts of the
language (with unfortunate names).

The delete[] statement, and the operator delete[].

When you write

delete[] ptr;

the compiler will turn this staement into a sequence of

a) calls the destructor for each element in the array
b) calls operator delete[](ptr)

If you haven't added an overload for your type, there is always a
global

void operator delete[](void* _Ptr) throw();

that the compiler can call.

:: 2. why if we use new[] to allocate memory, then use delete (other
:: than delete[]) will cause memory leak?

It might, or it might not. The rules of the language say that delete[]
must call all destructors, delete doesn't have to.

The intent is obviously that plain delete is used more often, and that
it possibly can run slightly faster if it doesn't have to figure out
the number of elements in the array. It can assume 1 always.

Probably doesn't make much difference in practice, but that's the way
it is.

:: 3. why there is a common delete[] which suits for all various
:: types of object (I ask this question because I always do not
:: overload operator delete in my class and delete[] always works)?

There is a global operator delete[], just like there is a global
operator new[]. The compiler sets proper parameter values from the
type info it has.

Bo Persson
George - 01 Nov 2007 08:45 GMT
Thanks Bo,

Your answer is comprehensive!

Two more comments,

1. about where is the global delete[]

> There is a global operator delete[], just like there is a global
> operator new[]. The compiler sets proper parameter values from the
> type info it has.

I am wondering where is the global delete[] you mentioned. In some global
namespace (e.g. std?), some global default base class or somewhere else?
Suppose I am using Visual Studio 2005 to develop C++.

2. about step b of the sequences

> a) calls the destructor for each element in the array
> b) calls operator delete[](ptr)

I can understand step a, but can not understand why step b is needed? I have
this question because I think step a is enough and why need step b (I think
if delete[] could trigger each destructor of instance of the instance array,
it should be enough)? Could you describe what is step b doing for example
please?

regards,
George

> :: Thanks Ben!
> ::
[quoted text clipped - 50 lines]
>
> Bo Persson
David Wilkinson - 01 Nov 2007 14:04 GMT
> Thanks Bo,
>
[quoted text clipped - 22 lines]
> it should be enough)? Could you describe what is step b doing for example
> please?

George:

Because under the hood, a call to new [] incurs a call to malloc(). So
delete [] has to call free() to release the memory.

Signature

David Wilkinson
Visual C++ MVP

George - 02 Nov 2007 07:13 GMT
Hi Dave,

I have two questions below, Your answer,

> Because under the hood, a call to new [] incurs a call to malloc(). So
> delete [] has to call free() to release the memory.

is for which question. Sorry that I am a little confused. :-)

have a good weekend,
George

> > Thanks Bo,
> >
[quoted text clipped - 27 lines]
> Because under the hood, a call to new [] incurs a call to malloc(). So
> delete [] has to call free() to release the memory.
David Wilkinson - 02 Nov 2007 13:20 GMT
> Hi Dave,
>
[quoted text clipped - 4 lines]
>
> is for which question. Sorry that I am a little confused. :-)

George:

Obviously, for your second question. You asked why it is necessary to
call operator delete [](ptr).

When you use new []

The memory is created by operator new [] (which uses malloc() by default)
Default constructors are called to create the objects

So when you call delete []

Destructors are called to clean up the objects
The memory is freed by operator delete [] (which uses free() by default)

Makes sense, no?

Signature

David Wilkinson
Visual C++ MVP

George - 02 Nov 2007 16:41 GMT
Thanks David,

Now I understand why I am confused. You mentioned,

> Destructors are called to clean up the objects
> The memory is freed by operator delete [] (which uses free() by default)

I think destructor itself could free the memory (please correct me if I am
not correct at this point), so there is no need to call operator delete[] to
free the memory again? :-)

If destructor could free memory occupied by the instances and delete[]
operator must free some other memory. :-)

Any comments?

regards,
George

> > Hi Dave,
> >
[quoted text clipped - 21 lines]
>
> Makes sense, no?
David Wilkinson - 02 Nov 2007 19:09 GMT
> Thanks David,
>
[quoted text clipped - 11 lines]
>
> Any comments?

George:

Yes. You are wrong. Every malloc() must have a free(). The destructors
of the individual objects cannot free the memory that was created for
the whole array by new [], because they do not know anything about it.

Destructors are not only called for objects allocated on the heap; they
are also called for objects on the stack.

Signature

David Wilkinson
Visual C++ MVP

George - 03 Nov 2007 06:43 GMT
Hi David,

Sorry for my confusion again. :-)

I will show you a sample. Suppose I have a class Foo and in this class
(constructor), I malloc 10 bytes, and in the destructor of this class I will
call free to release the 10 bytes.

Suppose some other components use new Foo[5] to malloc 10 * 5 = 50 bytes and
5 instances of Foo, then when we call delete[] with the pointer to Foo[5] we
malloced before, then the destructor will be invoked 5 times, and in each
time, 10 bytes will be freed (released). So the memory is balanced, right?

So, in my points, I think in delete[] implementation, invoking the
destructor for each instances is enough (see my sample above). I think I may
not correct and you are more experienced. But from the sample, I can not make
myself convinced about why you mentioned an additonal step should be used to
free the memory of the array?

regards,
George

> > Thanks David,
> >
[quoted text clipped - 20 lines]
> Destructors are not only called for objects allocated on the heap; they
> are also called for objects on the stack.
David Wilkinson - 03 Nov 2007 11:12 GMT
> Hi David,
> Sorry for my confusion again. :-)
[quoted text clipped - 13 lines]
> myself convinced about why you mentioned an additonal step should be used to
> free the memory of the array?

George:

I would strongly recommend that you read Scott Myers' "More Effective
C++", which has a good discussion of the difference between the "new
operator" and "operator new", and friends, and how to implement the latter.

Basically:

The new operator calls operator new to create the memory and then
constructs the object in that space.

The delete operator calls the destructor, and then calls operator delete
to free the memory.

You have no control over the new operator and delete operator; they are
part of the language. What you can control is the implementation of
operator new and operator delete. The default versions use malloc() and
free().

Likewise the [] forms of these.

You see that the separation of the object creation/destruction from the
memory creation/destruction is an intrinsic part of the C++ language,
and there is no point in discussing how it might be different.

If you provide your own new and delete operators (and [] forms) to
handle the memory part, then it is up to you to make sure that, as a
pair, they do not leak memory.

As others have mentioned, this question should have been asked in
microsoft.public.vc.language, because it has nothing to do with .NET.

Signature

David Wilkinson
Visual C++ MVP

George - 03 Nov 2007 15:05 GMT
Thanks David,

The last question,

I want to confirm with you after reading your reply,

1. when invoke delete (without []), the destructor will be invoked and then
the global delete operator will be invoked (as default);
2. when invoke delete[], the destructor for each instance element of the
array will be invoked and then the global delete operator will be invoked (as
default), and the global delete operator is the same in (1).

Right?

regards,
George

> > Hi David,
> > Sorry for my confusion again. :-)
[quoted text clipped - 45 lines]
> As others have mentioned, this question should have been asked in
> microsoft.public.vc.language, because it has nothing to do with .NET.
David Wilkinson - 03 Nov 2007 17:57 GMT
> Thanks David,
>
[quoted text clipped - 9 lines]
>
> Right?

George:

According to Scott Myers book, you are using the words wrong. The delete
operator is the one you call from your code. Operator delete is the one
that gets called after the destructor has been called; it the latter
that you can override (must override together with operator new).

Likewise for the [] versions.

It may or may not be true that operator new/delete are the same as
operator new/delete []. This depends on the implementation (your
implementation if you choose to override).

Signature

David Wilkinson
Visual C++ MVP

George - 04 Nov 2007 10:25 GMT
Thanks David,

I must buy and read the book "More Effective C++". Your clarification is so
clear.

regards,
George

> > Thanks David,
> >
[quoted text clipped - 22 lines]
> operator new/delete []. This depends on the implementation (your
> implementation if you choose to override).

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.