.NET Forum / Languages / Managed C++ / November 2007
delete []
|
|
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 MagazinesGet 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 ...
|
|
|