delete []

G

Guest

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
 
D

David Wilkinson

George said:
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? :)

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?
 
G

Guest

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

David Wilkinson said:
George said:
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? :)

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?
 
B

Ben Voigt [C++ MVP]

George said:
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?

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 ::blush:perator[]
regards,
George

David Wilkinson said:
George said:
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? :)

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?
 
G

Guest

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

Ben Voigt said:
George said:
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?

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 ::blush:perator[]
regards,
George

David Wilkinson said:
George wrote:
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? :)

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?
 
D

David Wilkinson

George said:
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)?

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.
 
P

Peter Oliphant

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==]

David Wilkinson said:
George said:
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)?

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.
 
B

Bo Persson

George wrote:
:: 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)?

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
 
C

Carl Daniel [VC++ MVP]

Peter said:
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
 
G

Guest

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

David Wilkinson said:
George said:
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)?

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.
 
G

Guest

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

David Wilkinson said:
George said:
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)?

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.
 
G

Guest

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

Bo Persson said:
George wrote:
:: 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)?

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
 
D

David Wilkinson

George said:
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?

George:

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

Ben Voigt [C++ MVP]

George said:
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?

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.
 
P

Peter Oliphant

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==]

Carl Daniel said:
Peter said:
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
 
G

Guest

Hi Ben,


Global namespace you mean namespace std?


regards,
George

Ben Voigt said:
George said:
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?

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.
 
G

Guest

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

David Wilkinson said:
George said:
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?

George:

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

David Wilkinson

George said:
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. :)

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?
 
G

Guest

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

David Wilkinson said:
George said:
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. :)

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?
 
S

SvenC

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
 

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

Top