Jump to content
  • Advertisement
Sign in to follow this  
digitalfreak

delete [] question

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

let Derived be a class that derives from class Base. now if I do this: Base *b = new Derived[10]; and later I do this: delete [] b; will the above delete[] properly release the memory allocated by new? how does it know to delete 10 Base or 10 Derived?

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by digitalfreak
will the above delete[] properly release the memory allocated by new?


The memory allocated for the array itself will be deallocated correctly. But...

Quote:
how does it know to delete 10 Base or 10 Derived?


It doesn't know.

Treating arrays polymorphically is a big no-no.

The compiler uses the (static) type of the pointer to determine how far aparts objects are located in the array. If Base and Derived have different sizes, delete[] will use the wrong offsets when calling the destructors.

For the destructors themselves, it relies on the virtual function table. Which is why, if you are going to delete a Derived object through a pointer to Base, Base need a virtual destructor. Of course, it is contingent on finding the objects in the expected places (see previous paragraph).

Share this post


Link to post
Share on other sites
No, it doesn't. You should either:


Derived *d = new Derived [10];
...
delete [] d;



or:


Base **b = new Base * [10];
for (int i = 0; i < 10; ++i) b = new Derived;
...
for (int i = 0; i < 10; ++i) delete b ;
delete [] b;

Share this post


Link to post
Share on other sites
Quote:
Original post by digitalfreak
then what's the solution?
delete [] (Derived *)b; //does this work?

Actually this will work, but you shouldn't do it. It will work only if you know b *definately* points to an array of Derived.....in which case you should be using Kippesoep's first example anyway.

Share this post


Link to post
Share on other sites
hi, I've just checked this with vc++ 2003.net
I watched the memory holding the array before and after delete, I could tell that the exact amount of memory that were allocted by new were released, no matter I use (Derived *) coercion or not.

so what does this imply?

Share this post


Link to post
Share on other sites
This would imply either Base and Derived are the same size, or you code was simple enough for the compiler to know what to do.

What were the sizes of Base and Derived?

Share this post


Link to post
Share on other sites
According to the C++ standard (Section 5.3.5 paragraph 3 for those of you keeping track at home) using delete [] on a pointer whose dynamic type differs from its static type has undefined behaviour. And undefined behaviour can mean cleaning up the memory properly and calling all of right the destructors.

It can also mean segfaulting and launching nuclear missiles at a cow ranch in Alaska.

However, judging from the generated disassembly, in a new project, with default compiler settings, etc. as long as the base class's destructor is virtual, MSVC 7.1 will free the proper amount of memory and call the right destructors. It's still not something I would rely on.

Share this post


Link to post
Share on other sites
As André LaMothe says on a similar subject, Although not COM objects are currently released automatically, not releasing COM objects might in the future create wormholes next to your head, to let's be on the safe side and release our COM objects.

Share this post


Link to post
Share on other sites
While the behavior of C++ when deleting a derived object through a base pointer may be undefined, the actual memory deallocation should work correctly. This does not, however, mean that the right destructors will be called.

C++ depends on a virtual memory allocator to satisfy requests for memory. The memory allocator returns blocks of at least the requested size or returns an error. Often, the region of memory returned is actually larger than requested so that it ends on a specific boundary (such as 8 bytes). The memory allocator tags each chunk of memory with a size value so that it knows how large each chunk is. When delete is called, the size value in the tag is used to determine how much memory must be deallocated not the size of the base or the derived object.

After the memory is deallocated, the chunk is placed in a free list of available blocks. In the GNU libc malloc implementation, each chunk of memory is tagged with the size of the current and the previous blocks. When the chunk is unallocated, a forward and back pointer are also stored in the chunk (after the size values) so that the chunk can be stored in doubly-linked list of free blocks. On allocation, the pointer values are not needed (it's not in the list anymore) so they are considered to be a part of the data region of the chunk.

Implementations of new and delete are more complicated than malloc and free because they must determine which constructors and destructors to call but the actual memory allocation should be very similar.

Steven

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!