array delete size mismatch - feature or bug?
Christian Szegedy
szegedy@or.uni-bonn.de
Tue May 8 06:10:00 GMT 2001
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
situation.
I read the faq at: http://cpptips.hyperformix.com/Ctordtor.html ,
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.
OK.
> 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
More information about the Gcc
mailing list