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

Discussion in 'C++' started by subramanian100in@yahoo.com, India, Apr 29, 2008.

  1. , India

    , India Guest

    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
    , India, Apr 29, 2008
    #1
    1. Advertising

  2. , India

    Jim Langston Guest

    Re: delete [] of Derived objects through Base object which has virtual dtor

    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
    Jim Langston, Apr 29, 2008
    #2
    1. Advertising

  3. , India

    Kai-Uwe Bux Guest

    Re: delete [] of Derived objects through Base object which has virtual dtor

    Jim Langston wrote:

    > 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
    Kai-Uwe Bux, Apr 29, 2008
    #3
  4. , India

    James Kanze Guest

    Re: delete [] of Derived objects through Base object which hasvirtual dtor

    On Apr 29, 4:32 am, ", India"
    <> 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:
    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
    James Kanze, Apr 29, 2008
    #4
  5. , India

    Jim Langston Guest

    Re: delete [] of Derived objects through Base object which has virtual dtor

    James Kanze wrote:
    > On Apr 29, 4:32 am, ", India"
    > <> 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
    Jim Langston, Apr 29, 2008
    #5
  6. , India

    Jim Langston Guest

    Re: delete [] of Derived objects through Base object which has virtual dtor

    Jim Langston wrote:
    > James Kanze wrote:
    >> On Apr 29, 4:32 am, ", India"
    >> <> 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
    Jim Langston, Apr 29, 2008
    #6
  7. , India

    , India Guest

    Re: delete [] of Derived objects through Base object which hasvirtual dtor

    * Kai-Uwe Bux <> wrote:
    > > 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
    , India, Apr 29, 2008
    #7
  8. , India

    Barry Guest

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

    , India wrote:
    > * Kai-Uwe Bux <> wrote:
    >>> 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"
    }
    Barry, Apr 29, 2008
    #8
  9. , India

    James Kanze Guest

    Re: delete [] of Derived objects through Base object which hasvirtual dtor

    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, ", India"
    > >> <> 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:
    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
    James Kanze, Apr 29, 2008
    #9
  10. , India

    xavier Guest

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

    Barry wrote:
    > , India wrote:
    >> * Kai-Uwe Bux <> wrote:
    >>>> 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
    xavier, May 12, 2008
    #10
  11. , India

    Ian Collins Guest

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

    xavier wrote:
    > Barry wrote:
    >>
    >> 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 ?
    >

    Both.

    --
    Ian Collins.
    Ian Collins, May 12, 2008
    #11
  12. , India

    James Kanze Guest

    Re: delete [] of Derived objects through Base object which hasvirtual dtor

    On May 13, 12:04 am, xavier <xavier> wrote:

    > > 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"
    > > }


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


    Objects are deleted, not parts of objects. Either the code has
    undefined behavior (and anything can happen), or delete will
    delete the entire object. (In this case, of course, it is the
    lattern.)

    --
    James Kanze (GABI Software) email:
    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
    James Kanze, May 13, 2008
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Zycor
    Replies:
    3
    Views:
    5,109
    David Harmon
    Dec 17, 2004
  2. qazmlp
    Replies:
    1
    Views:
    567
    qazmlp
    Apr 10, 2005
  3. Replies:
    4
    Views:
    407
    Alf P. Steinbach
    May 23, 2007
  4. Replies:
    1
    Views:
    394
    myork
    May 23, 2007
  5. Replies:
    1
    Views:
    386
    Victor Bazarov
    May 23, 2007
Loading...

Share This Page