tags:

views:

180

answers:

6

If I do this:

// (1.)
int* p = new int;
//...do something
delete p;

// (2.)
class sample
{
public:
sample(){}
~sample(){}
};
sample* pObj = new sample;
//...do something
delete pObj;

Then how does C++ compiler know that object following delete is built-in data type or a class object? My other question is that if I new a pointer to an array of int's and then I delete [] then how does compiler know the size of memory block to de-allocate?

+3  A: 

It knows the difference between them because of the type of the pointer you pass to it: It is undefined behavior to pass a different pointer type than you allocated with (except you may pass a pointer to a base class, if the destructor is virtual, of course).

The size of an array will be stored somewhere. It's like in C where you can malloc a certain amount of memory, and free afterwards - the runtime will have to manage to know the size allocated previously.

For example it can store the count of elements prior to the buffer allocated. The Standard explicitly allows the compiler to pass a different request size to the allocation function (operator new[]) in case of array allocations - this can be used by the compiler to stick the count into, and offset the address returned by the new expression by the size of that counter.

Johannes Schaub - litb
+1  A: 

It doesn't!

All what delete does is that it invokes the destructor of the type, which is "no action" in the case of primitive types. Then, it passes the pointer to ::operator delete (or an overloaded version if you like), and thats operator returns back the memory(a memory manager issue). i.e. You can write your own memory manager easily in C++ if you like, the language provides one by default!

AraK
+2  A: 
  1. The compiler knows the type of the object being deleted and writes different code for you to achieve the right results:
    • delete p can call the run time delete with the size of an int.
    • delete pObj can call pObj->~sample() first, then delete with the size of sample
  2. I think with arrays, there is a hidden value for the size of the array, so it could be that the whole array is deleted in one go.
quamrana
+1  A: 

Then how does C++ compiler know that object following delete is built-in data type or a class object?

Because at compile time the compiler tracks the types of each object and plants the appropraite code.

My other question is that if I new a pointer to an array of int's and then I delete [] then how does compiler know the size of memory block to de-allocate?

It does not. This is kept track of by the runtime system.
When you dynamically allocate an array the runtime library associates the size of the object with the object thus when it deletes it it knows (by looking up the associated value) the size.

But I guess you want to know how it does the association?
This depends on the system and is an implementation detail. But a simple stratergy is to allocate an extra 4 bytes store the size in the first four bytes then return a pointer to the 4th byte allocated. When you delete a pointer you know that the size is the 4 bytes before the pointer. Note: I am not saying your system is using this technique but it is one stratergy.

Martin York
+1  A: 
  1. The compiler knows the type of the pointed-to object because it knows the type of the pointer:

    • p is an int*, therefore the pointed-to object will be an int.
    • pObj is a sample*, therefore the pointed-to object will be a sample.
  2. The compiler does not if your int* p points to a single int object or to an array (int[N]): that's why you must remember to use delete[] instead of delete for arrays.

    The size of the memory block to de-allocate and, most importantly, the number of objects to destroy, are known because new[] stores them somewhere, and delete[] knows where to retrieve these values. This question from C++ FAQ Lite shows two common techniques to implement new[] and delete[].

Danilo Piazzalunga
A: 

For the first (non-array) part of the question, the answers above indicating that the compiler inserts code to de-allocate the appropriate number of bytes based on the pointer type, don't quite provide a clear answer for me... the delete operator 1) calls a destructor if applicable and then 2) calls the "operator delete()" function... it is operator delete which actually de-allocates. I can see compiler-generated code playing a role in part (1), ie. the destination address of the destructor must be inserted. But in part (2), it is a pre-existing library function handling the de-allocation, so how will it know the size of the data? The global operator delete--which, I believe is used in all cases unless a class-member/overloaded-global version is defined by the programmer--accepts only a void* argument spec'ing the start of the data, so it can't even be passed the data size. I've read things indicating the compiler-generated code idea, as well as things suggesting that the global operator delete for non-arrays simply uses free(), ie. it knows the data size not by the pointer type, but by looking a few bytes before the data itself, where the size will have been stashed by new/malloc. The latter is the only solution that makes sense to me, but maybe someone can enlighten me differently...

Josh