Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > delete [] of Derived objects through Base object which has virtualdtor

Reply
Thread Tools

delete [] of Derived objects through Base object which has virtualdtor

 
 
subramanian100in@yahoo.com, India
Guest
Posts: n/a
 
      04-29-2008
Suppose

class Base
{
public:
virtual ~Test() { ... }
// ...
};

class Derived : public Base
{
public:
virtual ~Derived() { ... }
// ...
};

int main()
{
Base* base_ptr = new Derived[10]();
delete [] base_ptr;
return EXIT_SUCCESS;
}

If the Base class dtor is not not virtual, 'delete [] base_ptr' has
undefined behaviour.

Will 'delete [] base_ptr' call each Derived class dtor because the
Base::~Base() is virtual ? Is the deletion in the above code valid ?.
Or does this also invoke undefined behaviour ?

Kindly clarify.

Thanks
V.Subramanian
 
Reply With Quote
 
 
 
 
Jim Langston
Guest
Posts: n/a
 
      04-29-2008
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> Suppose
>
> class Base
> {
> public:
> virtual ~Test() { ... }


Did you mean
virtual ~Base() { /*...*/ }
here?

> // ...
> };
>
> class Derived : public Base
> {
> public:
> virtual ~Derived() { ... }
> // ...
> };
>
> int main()
> {
> Base* base_ptr = new Derived[10]();
> delete [] base_ptr;
> return EXIT_SUCCESS;
> }
>
> If the Base class dtor is not not virtual, 'delete [] base_ptr' has
> undefined behaviour.
>
> Will 'delete [] base_ptr' call each Derived class dtor because the
> Base::~Base() is virtual ? Is the deletion in the above code valid ?.
> Or does this also invoke undefined behaviour ?


If Base is correct with a proper virtual Base destructor (and not Test
destructor which is invalid) I believe this is well formed code.

--
Jim Langston
(E-Mail Removed)


 
Reply With Quote
 
 
 
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      04-29-2008
Jim Langston wrote:

> (E-Mail Removed) wrote:
>> Suppose
>>
>> class Base
>> {
>> public:
>> virtual ~Test() { ... }

>
> Did you mean
> virtual ~Base() { /*...*/ }
> here?
>
>> // ...
>> };
>>
>> class Derived : public Base
>> {
>> public:
>> virtual ~Derived() { ... }
>> // ...
>> };
>>
>> int main()
>> {
>> Base* base_ptr = new Derived[10]();
>> delete [] base_ptr;
>> return EXIT_SUCCESS;
>> }
>>
>> If the Base class dtor is not not virtual, 'delete [] base_ptr' has
>> undefined behaviour.
>>
>> Will 'delete [] base_ptr' call each Derived class dtor because the
>> Base::~Base() is virtual ? Is the deletion in the above code valid ?.
>> Or does this also invoke undefined behaviour ?

>
> If Base is correct with a proper virtual Base destructor (and not Test
> destructor which is invalid) I believe this is well formed code.


Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:

... 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.


Best

Kai-Uwe Bux
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      04-29-2008
On Apr 29, 4:32 am, "(E-Mail Removed), India"
<(E-Mail Removed)> wrote:
> Suppose


> class Base
> {
> public:
> virtual ~Test() { ... }
> // ...
> };


> class Derived : public Base
> {
> public:
> virtual ~Derived() { ... }
> // ...
> };


> int main()
> {
> Base* base_ptr = new Derived[10]();
> delete [] base_ptr;
> return EXIT_SUCCESS;
> }


> If the Base class dtor is not not virtual, 'delete []
> base_ptr' has undefined behaviour.


> Will 'delete [] base_ptr' call each Derived class dtor because
> the Base::~Base() is virtual ? Is the deletion in the above
> code valid ?. Or does this also invoke undefined behaviour ?


As Kai-Uwe has pointed out, it is undefined behavior. More
generally, although the compiler will tranquilly convert
Derived* to Base* even if Derived* points to an array (because
it cannot know this), the resulting pointer can only be used as
a pointer to the first individual object. In you case, for
example, no only is the delete[] undefined behavior, but any use
of base_ptr to access the allocated array (e.g. base_ptr[1])
would be as well.

In general, don't use array new; prefer std::vector. And don't
try to make array elements polymorphic; it doesn't work. (Array
elements are values, and polymorphism only works through
pointers or references. If you need an array of polymorphic
types, you must use std::vector< Base* >, allocating and
deallocating each one manually.)


--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      04-29-2008
James Kanze wrote:
> On Apr 29, 4:32 am, "(E-Mail Removed), India"
> <(E-Mail Removed)> wrote:
>> Suppose

>
>> class Base
>> {
>> public:
>> virtual ~Test() { ... }
>> // ...
>> };

>
>> class Derived : public Base
>> {
>> public:
>> virtual ~Derived() { ... }
>> // ...
>> };

>
>> int main()
>> {
>> Base* base_ptr = new Derived[10]();
>> delete [] base_ptr;
>> return EXIT_SUCCESS;
>> }

>
>> If the Base class dtor is not not virtual, 'delete []
>> base_ptr' has undefined behaviour.

>
>> Will 'delete [] base_ptr' call each Derived class dtor because
>> the Base::~Base() is virtual ? Is the deletion in the above
>> code valid ?. Or does this also invoke undefined behaviour ?

>
> As Kai-Uwe has pointed out, it is undefined behavior. More
> generally, although the compiler will tranquilly convert
> Derived* to Base* even if Derived* points to an array (because
> it cannot know this), the resulting pointer can only be used as
> a pointer to the first individual object. In you case, for
> example, no only is the delete[] undefined behavior, but any use
> of base_ptr to access the allocated array (e.g. base_ptr[1])
> would be as well.
>
> In general, don't use array new; prefer std::vector. And don't
> try to make array elements polymorphic; it doesn't work. (Array
> elements are values, and polymorphism only works through
> pointers or references. If you need an array of polymorphic
> types, you must use std::vector< Base* >, allocating and
> deallocating each one manually.)


I understand what you are saying, but I don't understand why. Why should a
pointer from a std::vector<Base*> be treated any different than a pointer
from Base*[] ? You state that array elements are values, but aren't the
members of containers values also? And don't most implementations of
std::vector hold their data in arrays?

It seems totally... non-intuitive and wrong to me. Can you perhaps point to
where in the standard this is stated? This is something I'm going to have
to get my head around, and right now it's just not doing it.

Thanks.

--
Jim Langston
(E-Mail Removed)


 
Reply With Quote
 
Jim Langston
Guest
Posts: n/a
 
      04-29-2008
Jim Langston wrote:
> James Kanze wrote:
>> On Apr 29, 4:32 am, "(E-Mail Removed), India"
>> <(E-Mail Removed)> wrote:
>>> Suppose

>>
>>> class Base
>>> {
>>> public:
>>> virtual ~Test() { ... }
>>> // ...
>>> };

>>
>>> class Derived : public Base
>>> {
>>> public:
>>> virtual ~Derived() { ... }
>>> // ...
>>> };

>>
>>> int main()
>>> {
>>> Base* base_ptr = new Derived[10]();
>>> delete [] base_ptr;
>>> return EXIT_SUCCESS;
>>> }

>>
>>> If the Base class dtor is not not virtual, 'delete []
>>> base_ptr' has undefined behaviour.

>>
>>> Will 'delete [] base_ptr' call each Derived class dtor because
>>> the Base::~Base() is virtual ? Is the deletion in the above
>>> code valid ?. Or does this also invoke undefined behaviour ?

>>
>> As Kai-Uwe has pointed out, it is undefined behavior. More
>> generally, although the compiler will tranquilly convert
>> Derived* to Base* even if Derived* points to an array (because
>> it cannot know this), the resulting pointer can only be used as
>> a pointer to the first individual object. In you case, for
>> example, no only is the delete[] undefined behavior, but any use
>> of base_ptr to access the allocated array (e.g. base_ptr[1])
>> would be as well.
>>
>> In general, don't use array new; prefer std::vector. And don't
>> try to make array elements polymorphic; it doesn't work. (Array
>> elements are values, and polymorphism only works through
>> pointers or references. If you need an array of polymorphic
>> types, you must use std::vector< Base* >, allocating and
>> deallocating each one manually.)

>
> I understand what you are saying, but I don't understand why. Why
> should a pointer from a std::vector<Base*> be treated any different
> than a pointer from Base*[] ? You state that array elements are
> values, but aren't the members of containers values also? And don't
> most implementations of std::vector hold their data in arrays?
>
> It seems totally... non-intuitive and wrong to me. Can you perhaps
> point to where in the standard this is stated? This is something I'm
> going to have to get my head around, and right now it's just not
> doing it.


I found it. 5.3.5.3

Quote: In the first alternative (delete object), if the static type of the
operand is different from its dynamic type, the
static type shall be a base class of the operand's dynamic type and the
static type shall have a virtual
destructor or the behavior is undefined. 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.

--
Jim Langston
(E-Mail Removed)


 
Reply With Quote
 
subramanian100in@yahoo.com, India
Guest
Posts: n/a
 
      04-29-2008
* Kai-Uwe Bux <(E-Mail Removed)> wrote:
> > (E-Mail Removed) wrote:


> Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:
>
> ... 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.


I do not know about static and dynamic type.
Please give me an example so that I can understand them.

Thanks
V.Subramanian
 
Reply With Quote
 
Barry
Guest
Posts: n/a
 
      04-29-2008
(E-Mail Removed), India wrote:
> * Kai-Uwe Bux <(E-Mail Removed)> wrote:
>>> (E-Mail Removed) wrote:

>
>> Well formed -- maybe. But the code has undefined behavior as per [5.3.5/3]:
>>
>> ... 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.

>
> I do not know about static and dynamic type.
> Please give me an example so that I can understand them.
>


class Base
{
public:
virtual ~Base() {}
};

class Derived : public Base
{};

int main()
{
Base* p = new Derived(); // static type of p is "pointer to Base"
// dynamic type of p is "pointer to Derived"
}

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      04-29-2008
This is actually a response to the post you're responding to,
but since I cannot see it...

Jim Langston wrote:
> Jim Langston wrote:
> > James Kanze wrote:
> >> On Apr 29, 4:32 am, "(E-Mail Removed), India"
> >> <(E-Mail Removed)> wrote:
> >>> Suppose


> >> In general, don't use array new; prefer std::vector. And don't
> >> try to make array elements polymorphic; it doesn't work. (Array
> >> elements are values, and polymorphism only works through
> >> pointers or references. If you need an array of polymorphic
> >> types, you must use std::vector< Base* >, allocating and
> >> deallocating each one manually.)


> > I understand what you are saying, but I don't understand why. Why
> > should a pointer from a std::vector<Base*> be treated any different
> > than a pointer from Base*[] ? You state that array elements are
> > values, but aren't the members of containers values also? And don't
> > most implementations of std::vector hold their data in arrays?


Think about how you index into an array. And what pointer
arithmetic (which is how indexing is implemented) would mean if
you had to take into account the dynamic size. How would you
find p[1] without knowing the size of p[0]? And in the case of
p[2], what should be multiplied by 2, if p[0] and p[1] have
different sizes.

The problem here in C++ (which it inherits from C) is that even
at the user level, it makes the pointer arithmetic evident, and
doesn't distinguish between pointers to a single object, and
pointers to the first element in an array. Some of the things
you can do with a pointer (i.e. convert from Derived* to Base*)
only make sense for single objects, and other (anything
involving pointer arithmetic) only makes sense if the pointer is
in fact the address of an array.

> > It seems totally... non-intuitive and wrong to me. Can you perhaps
> > point to where in the standard this is stated? This is something I'm
> > going to have to get my head around, and right now it's just not
> > doing it.


> I found it. 5.3.5.3


> Quote: In the first alternative (delete object), if the static
> type of the operand is different from its dynamic type, the
> static type shall be a base class of the operand's dynamic
> type and the static type shall have a virtual destructor or
> the behavior is undefined. 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.


That covers the delete. Something like:

struct Base
{
virtual ~Base() {}
int i ; // Take up some room.
virtual void function() ;
}

struct Derived : Base
{
int j ; // Ensure that Derived is bigger than
// Base.
virtual void function() ;
} ;

Base* p = new Derived[ 20 ] ;
++ p ;
p->function() ;

is also illegal. It can't work; there's no way to implement it
so that it does work (within the usual C++ memory model). But
finding why in the standard... It's very, very indirect, but I
suppose that the definition of pointer addition (++ is defined
in terms of addition) would cover it: "When an expression that
has integral type is added to or subtracted from a pointer, the
result has the type of the pointer operand. If the pointer
operand points to an element of an array object,[...]" In this
case, the pointer points to a Base subobject, and that Base
subobject is NOT an element of an array object. (The elements
of the array object are all Derived.) I'd prefer something more
explicit, but I think that the intent is clear.

--
James Kanze (GABI Software) email:(E-Mail Removed)
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
 
Reply With Quote
 
xavier
Guest
Posts: n/a
 
      05-12-2008
Barry wrote:
> (E-Mail Removed), India wrote:
>> * Kai-Uwe Bux <(E-Mail Removed)> wrote:
>>>> (E-Mail Removed) wrote:

>>
>>> Well formed -- maybe. But the code has undefined behavior as per
>>> [5.3.5/3]:
>>>
>>> ... 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.

>>
>> I do not know about static and dynamic type.
>> Please give me an example so that I can understand them.
>>

>
> class Base
> {
> public:
> virtual ~Base() {}
> };
>
> class Derived : public Base
> {};
>
> int main()
> {
> Base* p = new Derived(); // static type of p is "pointer to Base"
> // dynamic type of p is "pointer to Derived"
> }
>


Hello,

in the above example, what will happen if we add 'delete p;' at the end
of main(). What will be deleted ? Only the base class part or both base
and derived part of instantied object ?

thanks

Xavier
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 01:44 PM
Derived::Derived(const Base&) and Derived& operator=(const Base&) developereo@hotmail.com C++ 1 05-23-2007 12:07 AM
Object creation - Do we really need to create a parent for a derieved object - can't the base object just point to an already created base object jon wayne C++ 9 09-22-2005 02:06 AM
Format of compiler generated derived destructor when base has 'virtual ~base() throw():" qazmlp C++ 1 04-10-2005 03:09 PM
delete derived class through base class pointer (?) Zycor C++ 3 12-17-2004 03:38 AM



Advertisments