Topic: Explicit call of operator delete


Author: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>
Date: 1995/12/11
Raw View
In article <4af46g$ht9@engnews1.eng.sun.com> clamage@eng.sun.com
(Steve Clamage) writes:

   [I've posted a copy of this to comp.std.c++, and set follow-ups
there, since I've simple triggered on one statement in the posting to
do some language lawyering...]

|> The placement-delete is just a function, and you can call it
|> explicitly. Example:

|>  void* operator new(size_t, int, char*); // placement new
|>  void operator delete(void*, int, char*); // corresponding delete
|>  ...
|>  T* p = new (5, "hello") T;
|>  ...
|>  p->~T(); // destroy the object
|>  operator delete(p, 5, "hello"); // recycle the storage

I've said things like this in the past too, but for some reason, it
just hit me that the last line above is illegal, or at least dubious.
The function operator delete requires a pointer to void; the language
rules require this to be the first byte of the actual object.  The
relationship between the first byte of the actual object and the
actual byte referenced by the pointer depends on the *dynamic* type of
the object.  The dynamic type.  After p->~T() has executed.

So I think you should replace the last two lines with:

 void*               tmp = p ;
 p->~T() ;
 operator delete( tmp , 5 , "hello" ) ;

I don't have a compiler which supports placement-delete on this
machine, so I've done basically the same thing with normal new and
delete.  You're welcome to try the following code, both with and
without -DCORRECT in the compiler invocation line.  IMHO, without the
-DCORRECT, you have undefined behavior, with, it should work.

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

    struct B1
    {
        int                 b1 ;
        virtual             ~B1() {}
    } ;

    struct B2
    {
        int                 b2 ;
        virtual             ~B2() {}
    } ;

    struct D : B1 , B2
    {
        virtual             ~D()
        {
            cout << "In D::~D()" << endl ;
        }
    } ;

    void*
    operator new( size_t n )
    {
        void*               p = malloc( n ) ;
        cout << "In op new, returning " << p << endl ;
        return p ;
    }

    void
    operator delete( void* p )
    {
        cout << "In op delete, freeing " << p << endl ;
        cout << flush ;
        free( p ) ;
    }

    int
    main()
    {
        B2*                 p = new D ;
        cout << "p = " << (void*)( p ) << endl ;
    #ifdef  CORRECT
        void*               tmp = p ;
        p->~B2() ;
        operator delete( tmp ) ;
    #else
        p->~B2() ;
        operator delete( p ) ;
    #endif
        return 0 ;
    }

The latest compiler I have here, g++ 2.6.3, core dumps in both cases,
after outputting a different address in the delete than in the free.
Given that the exact definition of the implicit cast to void has only
been clarified recently, I don't think that the compiler should be
criticized too harshly for not anticipating what the standards
committee was going to decide.

--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils,    tudes et r   alisations en logiciel orient    objet --
                -- A la recherche d'une activit    dans une region francophone


---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]





Author: James Kanze US/ESC 60/3/141 #40763 <kanze@lts.sel.alcatel.de>
Date: 1995/12/13
Raw View
In article <9512112019.AA05800@lts.sel.alcatel.de> James Kanze US/ESC
60/3/141 #40763 <kanze@lts.sel.alcatel.de> writes:

|> In article <4af46g$ht9@engnews1.eng.sun.com> clamage@eng.sun.com
|> (Steve Clamage) writes:

|> |> The placement-delete is just a function, and you can call it
|> |> explicitly. Example:

|> |>  void* operator new(size_t, int, char*); // placement new
|> |>  void operator delete(void*, int, char*); // corresponding delete
|> |>  ...
|> |>  T* p = new (5, "hello") T;
|> |>  ...
|> |>  p->~T(); // destroy the object
|> |>  operator delete(p, 5, "hello"); // recycle the storage

|> I've said things like this in the past too, but for some reason, it
|> just hit me that the last line above is illegal, or at least dubious.
|> The function operator delete requires a pointer to void; the language
|> rules require this to be the first byte of the actual object.  The
|> relationship between the first byte of the actual object and the
|> actual byte referenced by the pointer depends on the *dynamic* type of
|> the object.  The dynamic type.  After p->~T() has executed.

|> So I think you should replace the last two lines with:

|>  void*               tmp = p ;
|>  p->~T() ;
|>  operator delete( tmp , 5 , "hello" ) ;

In private email, Steve Clamage has pointed out to me that in fact,
the implicit conversion T* -> void* is the equivalent of a
static_cast, and only depends on the static type of *p.

This means that the above is also undefined behavior (and that g++ was
not in error in generating code that core dumped in this case.
Following Steve's suggestion, the first line should be:

 void*               tmp = dynamic_cast< void* >( p ) ;

--
James Kanze         Tel.: (+33) 88 14 49 00        email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils,    tudes et r   alisations en logiciel orient    objet --
                -- A la recherche d'une activit    dans une region francophone



---
[ comp.std.c++ is moderated.  Submission address: std-c++@ncar.ucar.edu.
  Contact address: std-c++-request@ncar.ucar.edu.  The moderation policy
  is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]