pointer casts and the heap

Discussion in 'C++' started by Wolfgang Jeltsch, Aug 30, 2003.

  1. Hello,

    say, I have a class A which is a subclass of a class B. If we look at the
    internal layout of a class A instance than most C++ implementations will
    place the members inherited from class B at the beginning and the members
    added in the class A declaration behind them, I think. If a pointer to A is
    casted to a pointer to B then no action is needed because the beginning of
    the A instance is a valid B instance.

    But if A is a subclass of both class B and class C, the situation is more
    difficult. An A instance cannot begin with the B and the C members at the
    same time. The compiler could for example place the B members first, then
    the C members and finally the actual A members. If then a cast from a
    pointer to A to a pointer to C would occur, the compiler would have to
    insert code for calculating a different address, namely the start address
    of the class C member part of the A instance.

    Now imaging that I do something like
    C *cPtr = new A;
    delete cPtr;
    Is this guaranteed to work correctly or doesn't the delete work as expected
    because the address given to it is different from the one returned by new.

    Thanks in advance for your answers.

    Wolfgang
     
    Wolfgang Jeltsch, Aug 30, 2003
    #1
    1. Advertising

  2. Wolfgang Jeltsch wrote:
    ....

    > Now imaging that I do something like
    > C *cPtr = new A;
    > delete cPtr;
    > Is this guaranteed to work correctly or doesn't the delete work as expected
    > because the address given to it is different from the one returned by new.


    This is not guarenteed to work.

    The conventional way to resolve this is to use a virtual destructor.

    class B { public virtual ~D(){} };
    class A { public virtual ~D(){} };

    class C : public A, public B {};

    A a = new C;

    B b = new C;

    delete a; //<< really calls C destructor

    delete b; //<< really calls C destructor

    If you new an object as class X you must delete it as class X. A
    virtual destructor will guarentee that the right destructor is called.
     
    Gianni Mariani, Aug 30, 2003
    #2
    1. Advertising

  3. "Gianni Mariani" <> wrote in message
    news:biqh37$...
    > Wolfgang Jeltsch wrote:
    > ...
    >
    > > Now imaging that I do something like
    > > C *cPtr = new A;
    > > delete cPtr;
    > > Is this guaranteed to work correctly or doesn't the delete work as

    expected
    > > because the address given to it is different from the one returned by

    new.
    >
    > This is not guarenteed to work.
    >
    > The conventional way to resolve this is to use a virtual destructor.
    >
    > class B { public virtual ~D(){} };
    > class A { public virtual ~D(){} };
    >
    > class C : public A, public B {};
    >
    > A a = new C;
    >
    > B b = new C;
    >
    > delete a; //<< really calls C destructor
    >
    > delete b; //<< really calls C destructor
    >
    > If you new an object as class X you must delete it as class X. A
    > virtual destructor will guarentee that the right destructor is called.
    >


    I was about to answer similarly but then I realised I wasn't sure whether it
    was necessary for both base classes to have virtual destructors? For
    instance in the OP's code

    struct C { ... };
    struct B { ... };
    struct A : B, C { ... };
    C *cPtr = new A;
    delete cPtr;

    Is it only necessary for C to have a virtual destructor for this code to be
    OK?

    john
     
    John Harrison, Aug 30, 2003
    #3
  4. > "Gianni Mariani" <> wrote in message
    > news:biqh37$...
    >
    >>This is not guarenteed to work.
    >>
    >>The conventional way to resolve this is to use a virtual destructor.
    >>
    >>class B { public virtual ~D(){} };
    >>class A { public virtual ~D(){} };


    Ummmm...

    >>
    >>class C : public A, public B {};
    >>
    >>A a = new C;
    >>
    >>B b = new C;


    Uhhhh...

    Maybe you meant:

    class B { public: virtual ~B() {} };
    class A { public: virtual ~A() {} };

    class C: public A, public B {};

    A *a = new C;
    B *b = new C;

    delete a;
    delete b;

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Aug 30, 2003
    #4
  5. Gianni Mariani wrote:

    > Wolfgang Jeltsch wrote:
    > ...
    >
    >> Now imaging that I do something like
    >> C *cPtr = new A;
    >> delete cPtr;
    >> Is this guaranteed to work correctly or doesn't the delete work as
    >> expected because the address given to it is different from the one
    >> returned by new.

    >
    > This is not guarenteed to work.
    >
    > The conventional way to resolve this is to use a virtual destructor.
    >
    > class B { public virtual ~D(){} };
    > class A { public virtual ~D(){} };
    >
    > class C : public A, public B {};
    >
    > A a = new C;
    >
    > B b = new C;
    >
    > delete a; //<< really calls C destructor
    >
    > delete b; //<< really calls C destructor


    Hello,

    I know that you have to use virtual destructors in order to guarantee that
    the right finalization is done. My question focused on a different point.

    As I explained, the address of the pointer to C is different from the
    address to the pointer to A. new allocates memory and returns a pointer to
    the beginning of the memory block. This pointer is of type (A *). It gets
    converted to type (C *). Probably, the resulting pointer denotes a
    different address. I think, it actually doesn't point to the beginning of
    the A instance but to the beginning of the C members inside the A instance.

    If I invoke the delete operator with this pointer to C then delete doesn't
    get the start address of the memory block but an address somewhere inside
    the block. The question is if this is guaranteed to work.

    > If you new an object as class X you must delete it as class X.


    You don't do so in the above example. You have new C but the delete
    operators get a pointer to A or B respectively. Or do you mean that you
    must delete it as class X, provided that no virtual destructors are used?

    > A virtual destructor will guarentee that the right destructor is called.


    Exactly.

    Wolfgang
     
    Wolfgang Jeltsch, Aug 30, 2003
    #5
  6. Wolfgang Jeltsch wrote:

    > Hello,
    >
    > say, I have a class A which is a subclass of a class B. If we look at the
    > internal layout of a class A instance than most C++ implementations will
    > place the members inherited from class B at the beginning and the members
    > added in the class A declaration behind them, I think. If a pointer to A
    > is casted to a pointer to B then no action is needed because the beginning
    > of the A instance is a valid B instance.
    >
    > But if A is a subclass of both class B and class C, the situation is more
    > difficult. An A instance cannot begin with the B and the C members at the
    > same time. The compiler could for example place the B members first, then
    > the C members and finally the actual A members. If then a cast from a
    > pointer to A to a pointer to C would occur, the compiler would have to
    > insert code for calculating a different address, namely the start address
    > of the class C member part of the A instance.
    >
    > Now imaging that I do something like
    > C *cPtr = new A;
    > delete cPtr;
    > Is this guaranteed to work correctly or doesn't the delete work as
    > expected because the address given to it is different from the one
    > returned by new.
    >
    > Thanks in advance for your answers.
    >
    > Wolfgang


    Hello again,

    I think I found the answer myself, and the answer is: "Yes, it is guaranteed
    to work." The C++ Draft Standard from around December 1996, available via
    http://www.csee.umbc.edu/help/C /index.shtml
    says in § 5.3.5 Delete:
    In the first alternative (delete object), the value of the operand of
    delete shall be a pointer to a non-array object created by a
    new-expression, or a pointer to a sub-object (1.7) representing a base
    class of such an object(10).
    I think, that the latter phrase covers the situation we talk about here.

    Wolfgang
     
    Wolfgang Jeltsch, Aug 30, 2003
    #6
  7. Wolfgang Jeltsch <> wrote in message news:<biqfr8$c1o74$-berlin.de>...

    > Now imaging that I do something like
    > C *cPtr = new A;
    > delete cPtr;
    > Is this guaranteed to work correctly or doesn't the delete work as expected
    > because the address given to it is different from the one returned by new.


    If C has a virtual destructor and A is derived from C, then yes, it is
    guaranteed to work. It doesn't matter that the C subobject of A does
    not share an address with the A object; C++ will adjust the pointer as
    necessary.

    - Shane
     
    Shane Beasley, Aug 31, 2003
    #7
  8. Wolfgang Jeltsch wrote:
    >
    > Hello again,
    >
    > I think I found the answer myself, and the answer is: "Yes, it is guaranteed
    > to work." The C++ Draft Standard from around December 1996, available via
    > http://www.csee.umbc.edu/help/C /index.shtml
    > says in § 5.3.5 Delete:
    > In the first alternative (delete object), the value of the operand of
    > delete shall be a pointer to a non-array object created by a
    > new-expression, or a pointer to a sub-object (1.7) representing a base
    > class of such an object(10).
    > I think, that the latter phrase covers the situation we talk about here.
    >


    OK, but you still need the virtual destructor or else all bets are off.

    -Kevin
    --
    My email address is valid, but changes periodically.
    To contact me please use the address from a recent posting.
     
    Kevin Goodsell, Aug 31, 2003
    #8
    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. Pointer to Structure Casts

    , Sep 21, 2005, in forum: C Programming
    Replies:
    5
    Views:
    549
  2. Michal Slocinski

    Heap dump file size vs heap size

    Michal Slocinski, Mar 25, 2008, in forum: Java
    Replies:
    1
    Views:
    788
    GArlington
    Mar 25, 2008
  3. viki
    Replies:
    6
    Views:
    647
    Erik Wikström
    Jun 28, 2008
  4. Raymond Schanks
    Replies:
    0
    Views:
    619
    Raymond Schanks
    Apr 11, 2010
  5. Jef Driesen

    Union and pointer casts?

    Jef Driesen, Feb 24, 2011, in forum: C Programming
    Replies:
    13
    Views:
    735
    Ben Bacarisse
    Apr 8, 2011
Loading...

Share This Page