This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

array delete size mismatch - feature or bug?

Thanks you for the answers to my previous question!

(size of derived class misfeature, I followed the suggestion of Biswa
 and it worked. )

This encouraged me to pose a new one, which I am quite unsure about.

C++ has a feature of passing object sizes to the delete operator.

I tested this with the following program and g++ 2.95.2 and 2.95.3:


#include <stdlib.h>
#include <iostream.h>

class A
public :
   int a[3];
   void *operator new(size_t s)
      void *p = malloc(s);
      cout<<"new A "<<p<<" of size "<<s<<endl;
      return p;

   void *operator new[](size_t s)
      void *p = malloc(s);
      cout<<"new A[] "<<p<<" of size "<<s<<endl;
      return p;

   void operator delete(void *p,size_t s)
      cout<<"delete A "<<p<<" of size "<<s<<endl;

   void operator delete[](void *p,size_t s)
      cout<<"delete A[] "<<p<<" of size "<<s<<endl;

class B : public A
public :
   int a[4];

void main()
   A *a  = new A;
   A *a5 = new A[5];
   B *b  = new B;
   B *b5 = new B[5];
   delete   a;
   delete[] a5;
   delete   b;
   delete[] b5;


The program outputs:

new A 0x8058da0 of size 12
new A[] 0x8058db0 of size 64
new A 0x8058df8 of size 28
new A[] 0x8058e18 of size 140
delete A 0x8058da0 of size 12
delete A[] 0x8058db0 of size 64
delete A 0x8058df8 of size 28
delete A[] 0x8058e18 of size 4060

So you can see that size of the delete[] operator for the
derived class is wrong.

You could object that this does not work because the destructor
of class A is not virtual. In fact, it works if I do it that way,
but of course, introduces some memory overhead.

Actually, I learned that I only need to declare A to be virtual 
if I want to delete an object of the inherited class given by a 
pointer of the BASE class.
Here, I would like to delete the object of type B given
by a pointer B*. So the binding can be done compile time,
It could work in principle...

To my understanding the compiler could generate a code for computing
the correct size under the assumption that the object has been
generated by a new B[???] statement, such as in the nonarray

I read the faq at:,
but found nothing related.

Then I looked at the draft of ANSI/ISO C++ specification.

I am not sure that I have not overlooked anything, but I found
only following instructions applicable to this situation:

It says:

>                    In the second alternative (delete array), the value
> of the operand of delete shall be the  pointer  value  which  resulted
> from a previous array new-expression.18) If not, the behavior is unde-
> fined.  

Obviously not the case.

> In the second alternative  (delete  array)  if  the dynamic type of 
> the object to be deleted differs from its static type, 
> the behavior is undefined.19)

I my case: both dynamic and static types are B, seems to be OK.

> If class T does not declare such an operator delete[] but does declare  a
> member  deallocation function named operator delete[] with exactly two
> parameters, the second of which has type std::size_t, then this  func-
> tion is a usual deallocation function.


> When  a delete-expression is executed, the selected deallocation func-
> tion shall be called with the address of the block of  storage  to  be
> reclaimed  as  its  first  argument and (if the two-parameter style is
> used) the size of the block as its second argument.3)

My questions are:

Is this a feature or a bug?

Does anybody know what the ISO standard says about this?

Thanks, Christian

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]