Topic: Just how smart is "delete"?


Author: James.Kanze@dresdner-bank.com
Date: 1999/04/29
Raw View
In article <QduBroAYDuJ3Ewu4@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>
> In article <7g5jfk$qbv$1@nnrp1.dejanews.com>, gbush@my-dejanews.com
> writes
> >Correct me if I'm wrong, but it seems to me that compilers could easily
> >implement the identification of correct type of a pointer. All compilers in
> >one way or another keep information about memory allocations. All they need
> >to do is to add one more byte for each allocation: offset of destructor in
> >vtable, or 0 if there is no one. Then the destruction of void* would be
> >trivial. Gene.
>
> But at a cost that very few would want to pay (not least that every type
> would need a vtable.

How much is the cost, really.  On the platforms I'm familiar with,
pointers are 4 bytes, and the maximum alignment requirement is 8 bytes
(for a double).  All of the allocation strategies I'm familiar with use
a single pointer before the returned block.  But the alignment
requirements require the "lost" space to be at least 8 bytes.  The
result is that they currently have 4 unused bytes in which to put the
address of a trampoline to the destructor, or a null pointer if there is
no destructor.

Total cost in space: 0.  In run-time one additional memory write per
allocation.  Rather negligible compared to the allocation itself.

> particularly as it only fixes a problem with ill-
> conceived design.

Which is a separate argument.  About the only conceivable use I can see
for new[] is when C compatibility is an issue -- otherwise, the
alternatives like vector are superior.  (And of course, any reasonable
implementation of something as fundamental as vector will separate
allocation and construction -- this is required in vector, but was true
long before anyone had even heard of STL.)

--
James Kanze                         mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                        Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany  Tel. +49 (069) 63 19 86 27

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: David R Tribble <dtribble@technologist.com>
Date: 1999/05/04
Raw View
Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
>> But at a cost that very few would want to pay (not least that every
>> type  would need a vtable. particularly as it only fixes a problem
>> with ill-conceived design.

gbush@my-dejanews.com wrote:
> Is it really such a big price to pay? On 32-bit platforms each object
> cannot be less than 4 bytes (size of vmt), but in average much bigger.
> So the worst case we have 25% increase. For 64-bit platforms, you
> don't really need 64-bits for vmt pointer, so one byte can be reserved
> for this purposes without any sacrifice. The worst case is when the
> program allocates char size chunks. Here we have 2 times increase in
> memory consumption. But I've never seen such a program, not even in C.
> This is completely insane to allocate 1 byte in a time. So for all
> practical purposes the memory usage will be negligibly higher.

You're only considering single objects allocated on the heap.
Consider a large auto array of objects that are only 16 bits wide.
Each member of the array (which could contain millions of members)
only requires 'short' alignment.

    class Foo
    {
    public:
                Foo();
                ~Foo();
    private:
        short   s;   // Object is only 16 bits wide
    };

    void Bar()
    {
        Foo     a[1000000];    // Calls Foo::Foo() many times

        ...
        bar(&a[i]);
        ...

        // About to call Foo::~Foo() many times
    }

    void bar(Foo *f)
    {
        // Can't tell if *f is dynamic, auto, or static
        ...
    }

By mandating that each object has extra hidden information in it,
you've just doubled (or tripled) the size of my data.

Here's an an example that uses heap objects, lest you think the
object bloat only affects auto objects:

    void baz()
    {
        Foo *  f;

        f = new Foo[1000000];  // Many Foo objects
        ...
        bar(&f[i]);
        ...
        delete[] f;
    }

Whereas the compiler could have packed a million Foo objects into
2MB, it now has to use 4MB (or maybe even 6MB) to allow for the
extra hidden info on each object.

Most programmers would consider a 25% space increase too high a
price to pay for *any* new feature.  Where's the benefit that
justifies this kind of cost?

Just because you've never seen "insane" programs before doesn't
mean there aren't any, or that they really are all useless.  Don't
go trying to break all of them to just because of some ill-conceived
"benefit".

-- David R. Tribble, dtribble@technologist.com --
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/04/28
Raw View
In article <7g5jfk$qbv$1@nnrp1.dejanews.com>, gbush@my-dejanews.com
writes
>Correct me if I'm wrong, but it seems to me that compilers could easily
>implement the identification of correct type of a pointer. All compilers in
>one way or another keep information about memory allocations. All they need
>to do is to add one more byte for each allocation: offset of destructor in
>vtable, or 0 if there is no one. Then the destruction of void* would be
>trivial. Gene.

But at a cost that very few would want to pay (not least that every type
would need a vtable. particularly as it only fixes a problem with ill-
conceived design.

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@dirac.ceg.uiuc.edu (Siemel Naran)
Date: 1999/04/28
Raw View
On 28 Apr 1999 04:58:46 GMT, gbush@my-dejanews.com
>  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:

>> But I think that requires the program to be able to recognise a vptr as
>> being such.

>Correct me if I'm wrong, but it seems to me that compilers could easily
>implement the identification of correct type of a pointer. All compilers in
>one way or another keep information about memory allocations. All they need
>to do is to add one more byte for each allocation: offset of destructor in
>vtable, or 0 if there is no one. Then the destruction of void* would be
>trivial. Gene.

Fine.  But allowing
   delete static_cast<void*>(ptr);
to work seems to reduce the benefit of strong typing.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: gbush@my-dejanews.com
Date: 1999/04/28
Raw View
In article <slrn7ie599.lls.sbnaran@dirac.ceg.uiuc.edu>,
  sbnaran@KILL.uiuc.edu wrote:
> Fine.  But allowing
>    delete static_cast<void*>(ptr);
> to work seems to reduce the benefit of strong typing.

Since, there is only one correct way to destroy an object, namely, using a
destructor corresponding to the dynamic type of an object pointer, all the
casts should be considered errelevant.

Gene Bushuyev.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: gbush@my-dejanews.com
Date: 1999/04/28
Raw View
In article <QduBroAYDuJ3Ewu4@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> But at a cost that very few would want to pay (not least that every type
> would need a vtable. particularly as it only fixes a problem with ill-
> conceived design.
>

Is it really such a big price to pay? On 32-bit platforms each object cannot
be less than 4 bytes (size of vmt), but in average much bigger. So the worst
case we have 25% increase. For 64-bit platforms, you don't really need
64-bits for vmt pointer, so one byte can be reserved for this purposes
without any sacrifice. The worst case is when the program allocates char size
chunks. Here we have 2 times increase in memory consumption. But I've never
seen such a program, not even in C. This is completely insane to allocate 1
byte in a time. So for all practical purposes the memory usage will be
negligibly higher.

Gene.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1999/04/28
Raw View
Gernot wrote:
....
> int* pInt = new int;
> delete (void*)pInt;
>
> >Sorry. This will work in most cases, but it simply isn't standard.
>
> If you take a look at what the standard says about the default
> implementations of operator new( size_t sz ) and operator delete( void*
> ) - and these are the only functions involved here - you'll find that
> delete shall behave as follows:
> "For such a non-null value of ptr, reclaims storage allocated by the
> earlier call to the default operator new."
>
> So this should really work in any case.

No - if a compiler chooses to allow it, it's likely to do the right
thing, in this special case. But this is illegal code, and compilers are
allowed to reject it, and I hope that any compiler I use will at least
produce a warning message for such code.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/29
Raw View
Ewert_Ahr._Electronic_GmbH@t-online.de (Gernot) writes:

>OK, it may not be LEGAL. This seems to be the wrong newsgroup to answer
>the original question. I just don't get it why all the answers in this
>thread tend to look at vtables, (virtual) destructors etc.

It depends on what kind of answer you want. If you want to know
whether a piece of code is valid according to the language
definition, this is the right place to ask it. You got an
answer, you but don't seem to like it. :-)

>Remember: The poster merely asked whether deallocation would be handled
>properly if he executed the statements

>int* pInt = new int;
>delete (void*)pInt;

>>Sorry. This will work in most cases, but it simply isn't standard.

>If you take a look at what the standard says about the default
>implementations of operator new( size_t sz ) and operator delete( void*
>) - and these are the only functions involved here - you'll find that
>delete shall behave as follows:
>"For such a non-null value of ptr, reclaims storage allocated by the
>earlier call to the default operator new."

>So this should really work in any case.

You are confusing new-expressions with operator new, and
delete-expression with operator delete.

The original code consists of a new-expression and a delete-
expression. The language definition describes their semantics.
Part of the definition says that if the type of the pointer
in the delete-expression does not fulfill certain requirements,
the expression has no defined behavior. The types do not fulfill
those requirements, so the code has no defined behavior.

The text you are quoting is about operator new and operator
delete. If you wrote instead
 int* pInt = operator new(sizeof(int));
 operator delete((void*)pInt);
the part of the standard you quoted does apply. This version
of the code is valid, and nobody said it wasn't.

[It is only valid modulo a missing cast to int*.
 No followups just to say that please. --mod]

But the orignal code is not valid.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/04/26
Raw View
In article <MPG.118bf4fc53c73cb9989a12@news.rmi.net>, Jerry Coffin
<jcoffin@taeus.com> writes
>Assuming T has at least one virtual member, why couldn't the run-time
>system figure out its real type, and delete it correctly?  It has to
>have the information about its real type available when/if you attempt
>to do a dynamic_cast, and that information _should_ be sufficient to
>let it delete the object correctly as well, shouldn't it?

But I think that requires the program to be able to recognise a vptr as
being such.


Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@eng.sun.com (Steve Clamage)
Date: 1999/04/26
Raw View
jcoffin@taeus.com (Jerry Coffin) writes:

>In article <slrn7i1tvo.6qt.sbnaran@bardeen.ceg.uiuc.edu>,
>sbnaran@bardeen.ceg.uiuc.edu says...

>[ ... ]

>> int main()
>> {
>>    T * i = new T();
>>    void * v = i;
>>    delete v; // IMHO, this should be an error!
>> }

>Assuming T has at least one virtual member, why couldn't the run-time
>system figure out its real type, and delete it correctly?  It has to
>have the information about its real type available when/if you attempt
>to do a dynamic_cast, and that information _should_ be sufficient to
>let it delete the object correctly as well, shouldn't it?

Let's make the example a bit more general:

file1.cc
--------
void g(void*);
int main()
{
    T* t = new T;
    g(t);
}


file2.cc
--------
void g(void* v)
{
    delete v;
}


Given "v", how does the runtime system determine that it really points
to a class object with a virtual destructor? In many implementations,
the location of the vtable or RTTI information is not known unless
the type of the object is known. Even if the standard were to place
requirements on implementations such that the vtable and/or RTTI
information must be at, e.g., zero offset from the object pointer,
how do you tell that *v really points to information of that kind?
You'd have to add signatures so that random data is unlikely to look
like vtable/RTTI data.

And what do all these restrictions buy you? You still cannot rely
on deleting a void* to do the right thing, because not all classes
are polymorphic.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1999/04/26
Raw View
On 25 Apr 99 15:38:34 GMT, Jerry Coffin <jcoffin@taeus.com> wrote:

>>    T * i = new T();
>>    void * v = i;
>>    delete v; // IMHO, this should be an error!

>Assuming T has at least one virtual member, why couldn't the run-time
>system figure out its real type, and delete it correctly?  It has to
>have the information about its real type available when/if you attempt
>to do a dynamic_cast, and that information _should_ be sufficient to
>let it delete the object correctly as well, shouldn't it?

But the implementation does not know whether the object pointed to by
'v' is polymorphic or not.  If it is polymorphic, then it has a
virtual pointer, and then typeid(*v) works because it can expect the
object pointed to by 'v' to have a virtual pointer.  But the object
pointed to by 'v' could very well not have a virtual pointer.  In
my first post, I wrote that if every class derived from void and
void::~void() were virtual, then typeid(*v) and delete v should
always work.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "AllanW {formerly AllanW@my-dejanews.com}" <allan_w@my-dejanews.com>
Date: 1999/04/26
Raw View
In article <aVTR2.738$Ey4.584@news.rdc1.tx.home.com>,
  "Brandon Jackson" <erreichbar@hotmail.com> wrote:
> Hello there,
>
> I've got a rather interesting question about "new" and "delete".
>
> Question:  Will "delete" handle deallocation properly if the following code
> were used
>
> int * pInt;
> pInt = new int;
>
> delete (reinterpret_cast<void *> (pInt));

In article <7fld8t$pmn$1@nnrp1.dejanews.com>, I replied
> This is not valid C++.
>
> As a practical matter, it should work correctly on most platforms
> provided that the data (in this case an int) does not have a destructor.
> But seeing as how you asked the question in a newsgroup about standards,
> no, this is clearly NOT legal.

That seems to have sparked some controversy.
In article <37207F40.177@eae.com>, neppert.gernot@eae.com wrote:
> I think this is perfectly legal. The poster was asking about different
> builtin types, not arbitrary (class) types.
> 1. All builtin types do not need a destructor call.
> 2. You cannot overload the new/delete operator differently for different
> builtin types.
> 3. The standard 1-argugment global delete operator does not get any
> information about object size, so it must handle deallocation by itself
> anyway.

This is a logical proof that the standard *COULD* have made this legal.
There would probably be additional overhead, but not much more.
However, the standard *DOES NOT* in fact allow this. From 5.3.5:

   1  The delete-expression operator destroys a most-derived object (1.8)
      or array created by a new-expression.
         delete-expression:
            ::opt delete cast-expression
            ::opt delete [ ] cast-expression
      The first alternative is for non-array objects, and the second is
      for arrays. ...[snip]...

   3  In the first alternative (delete object), if the static type of
      the object is different from it's dynamic type, the static type
      shall be a base class of the operator'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.

> Conclusion:
> For any two given builtin types T1, T2 the following code is legal:
>     T1* p = new T1;
>     delete (T2*)p;

Sorry. This will work in most cases, but it simply isn't standard. The
static type of *p is T1 and the dynamic type of *(T2*)p is T2. Since
this is the non-array case T2 must be derived from T1 for this to work,
and T1 must have a virtual destructor. By "builtin types" I assume that
you refer to the Fundamental Types of section 3.9.1 -- integral and
floating types. These are never related by derivation and never have
virtual destructors. Thus, this is never legal for those types.

Note also that void isn't really a type, although void* is. Many people
would like to consider int, et. al., to be "derived" from void -- but
it isn't.

In article <slrn7i1tvo.6qt.sbnaran@bardeen.ceg.uiuc.edu>,
  "Siemel B. Naran" sbnaran@KILL.uiuc.edu wrote:
>On 23 Apr 99 22:14:24 GMT, Gernot
>Conclusion:
>For any two given builtin types T1, T2 the following code is legal:
> It appears so.
... meaning that you agree that the example is legal?

> I found to my dismay that the following program compiles
> and runs on egcs.  The destructor T::~T() is not called.
>
> #include <iostream.h>
> struct T { virtual ~T(){cout<<"T dtor\n";} };
> int main()
> {
>    T * i = new T();
>    void * v = i;
>    delete v; // IMHO, this should be an error!
> }
Here you do not demonstrate that the code is legal; you demonstrate
that it has a problem!

This has an error. In the delete expression, the static type is void
(which isn't even a type), but the dynamic type is T. Nothing derives
from void, so this is always an error.

Perhaps you suggest that the code must be legal because you do not see
an error message? Undefined behavior does not require a diagnostic
message. I refer you to the definitions in 1.13:

   1.13.12 undefined behavior                    [defns.undefined]
   behavior, such as might arise upon use of an erroneous program
   construct or erroneous data, for which this International Standard
   imposes no requirements. Undefined behavior may also be expected
   when this International Standard omits the description of any
   explicit definition of behavior.
   [Note: permissible undefined behavior ranges from IGNORING THE
   SITUATION COMPLETELY WITH UNPREDICTABLE RESULTS, to behaving
   during translation or program execution in a documented manner
   characteristic of the environment (with or without the issuance
   of a diagnostic message), to terminating a translation or
   execution (with the issuance of a diagnostic message). Many
   erroneous program constructs do not engender undefined behavior;
   they are required to be diagnosed. ]

[Emphasis added]

In article <MPG.118bf4fc53c73cb9989a12@news.rmi.net>,
  jcoffin@taeus.com (Jerry Coffin) wrote:
[Referring to Siemel B. Naran's example]
> Assuming T has at least one virtual member, why couldn't the run-time
> system figure out its real type, and delete it correctly?  It has to
> have the information about its real type available when/if you attempt
> to do a dynamic_cast, and that information _should_ be sufficient to
> let it delete the object correctly as well, shouldn't it?

The requirement that T has at least one virtual member would mean that
the object has a vtable pointer, right? But the delete-expression uses
a void*, so how is the compiler expected to KNOW that the object has
a virtual pointer? The object could be a char! Would you want the
compiler to analyze the first few bytes to see if they happen to point
to some valid vtable somewhere? What if a vtable pointer just happened
to be the same size as a long, and some long on the heap happened to
have the same value as the address of X's vtable. When you delete the
int, you wouldn't want to call X's destructor, would you?

Finally, even if the compiler is able to figure out that this really is
some object with a vtable, that doesn't mean that the destructor is
one of the virtual functions. If it isn't, we have no way of knowing
how to call the constructor. Perhaps we could store the destructor
address in the private clas information, or perhaps (behind the
programmer's back) we could always make the destructor virtual if even
one other function is virtual -- but the suggestion that the existing
information is always sufficient to delete the object simply isn't so.

----
Allan_W@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/04/26
Raw View
In article <slrn7i1tvo.6qt.sbnaran@bardeen.ceg.uiuc.edu>,
  sbnaran@KILL.uiuc.edu wrote:
[snip]
> It appears so.  I found to my dismay that the following program compiles
> and runs on egcs.  The destructor T::~T() is not called.
>
> #include <iostream.h>
>
> struct T { virtual ~T(){cout<<"T dtor\n";} };
>
> int main()
> {
>    T * i = new T();
>    void * v = i;
>    delete v; // IMHO, this should be an error!
> }

It may not generate a compiler error, but it *is* undefined behaviour, since
the dynamic type of the operand of 'delete' is not the same as the static
type, nor is it a class unambiguously derived from the static type.  And you
know what can happen with undefined behaviour.... OK, maybe you don't ;-)

I don't know if I'd expect a compiler error (given that this type of behavior
is difficult to detect in all cases), but certainly (as a QOI issue) a good
compiler could warn about it.

--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post here.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/04/26
Raw View
In article <3721E6C8.2010@wanadoo.fr>,
  Valentin Bonnard <Bonnard.V@wanadoo.fr> wrote:
[snip]
> It is, that's precisely the purpose of void*. By the way, you should
> use static_cast, as you are really casting back to a derived type
> (assuming every type is derived from void (a natural view of things)).
Oops - goes to show how often I use casting ;-)

--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post here.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/04/27
Raw View
Jim Hyslop wrote:
>
> In article <slrn7i1tvo.6qt.sbnaran@bardeen.ceg.uiuc.edu>,
>   sbnaran@KILL.uiuc.edu wrote:

> > int main()
> > {
> >    T * i = new T();
> >    void * v = i;
> >    delete v; // IMHO, this should be an error!
> > }

> I don't know if I'd expect a compiler error (given that this type of behavior
> is difficult to detect in all cases),

It's certainly very difficult to predict that the dynamic
type of the object isn't void...

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <dtribble@technologist.com>
Date: 1999/04/27
Raw View
Jerry Coffin <jcoffin@taeus.com> wrote:
> >>    T * i = new T();
> >>    void * v = i;
> >>    delete v; // IMHO, this should be an error!
>
>> Assuming T has at least one virtual member, why couldn't the run-time
>> system figure out its real type, and delete it correctly?  It has to
>> have the information about its real type available when/if you
>> attempt to do a dynamic_cast, and that information _should_ be
>> sufficient to let it delete the object correctly as well, shouldn't
>> it?

Siemel Naran wrote:
> But the implementation does not know whether the object pointed to by
> 'v' is polymorphic or not.  If it is polymorphic, then it has a
> virtual pointer, and then typeid(*v) works because it can expect the
> object pointed to by 'v' to have a virtual pointer.  But the object
> pointed to by 'v' could very well not have a virtual pointer.

> In my first post, I wrote that if every class derived from void and
> void::~void() were virtual, then typeid(*v) and delete v should
> always work.

This would be equivalent to mandating that all classes are
implicitly derived from std::Object (or something similar), ala
Java, Eiffel, and others.  The drawback to this, and one of the
major differences between C++ and these languages, is that it
would require all class type objects to have the overhead of a
_vtbl.  (It would also complicate the use of PODs, if not outlawing
them outright, and classes derived from PODs.)  That is not what
Stroustrup intended; classes without virtual functions shouldn't
incur this overhead.

It becomes a question of how "pure" an object-oriented language
should C++ be.  As a pure O-O language, we'd have only virtual
functions and an implicit root Object class type, but we wouldn't
have PODs and non-indirect member function calls.  (We probably
wouldn't have pointers either, but that might not be so bad.)

-- David R. Tribble, dtribble@technologist.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Ewert_Ahr._Electronic_GmbH@t-online.de (Gernot)
Date: 1999/04/27
Raw View
> This is a logical proof that the standard *COULD* have made this legal.
> There would probably be additional overhead, but not much more.
> However, the standard *DOES NOT* in fact allow this. From 5.3.5:
>
>    1  The delete-expression operator destroys a most-derived object (1.8)
>       or array created by a new-expression.
>          delete-expression:
>             ::opt delete cast-expression
>             ::opt delete [ ] cast-expression
>       The first alternative is for non-array objects, and the second is
>       for arrays. ...[snip]...
>
>    3  In the first alternative (delete object), if the static type of
>       the object is different from it's dynamic type, the static type
>       shall be a base class of the operator'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.
>

OK, it may not be LEGAL. This seems to be the wrong newsgroup to answer
the original question. I just don't get it why all the answers in this
thread tend to look at vtables, (virtual) destructors etc.
Remember: The poster merely asked whether deallocation would be handled
properly if he executed the statements

int* pInt = new int;
delete (void*)pInt;


>Sorry. This will work in most cases, but it simply isn't standard.

If you take a look at what the standard says about the default
implementations of operator new( size_t sz ) and operator delete( void*
) - and these are the only functions involved here - you'll find that
delete shall behave as follows:
"For such a non-null value of ptr, reclaims storage allocated by the
earlier call to the default operator new."

So this should really work in any case.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@dirac.ceg.uiuc.edu (Siemel Naran)
Date: 1999/04/27
Raw View
On 27 Apr 1999 15:12:31 GMT, Gernot

>delete (void*)pInt;

>So this should really work in any case.

What do you mean by "should"?
According to the actual standard or according to the ideal standard?
In the actual standard, it works.
In the ideal standard, it doesn't -- because no destructor is called.
I believe the rule is inherited from C, where there are no destructors,
so the expression "delete (void*)pInt" must always work.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: gbush@my-dejanews.com
Date: 1999/04/28
Raw View
In article <fVcCJIAVE2I3EwGQ@robinton.demon.co.uk>,
  Francis Glassborow <francisG@robinton.demon.co.uk> wrote:
> But I think that requires the program to be able to recognise a vptr as
> being such.
>

Correct me if I'm wrong, but it seems to me that compilers could easily
implement the identification of correct type of a pointer. All compilers in
one way or another keep information about memory allocations. All they need
to do is to add one more byte for each allocation: offset of destructor in
vtable, or 0 if there is no one. Then the destruction of void* would be
trivial. Gene.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James.Kanze@dresdner-bank.com
Date: 1999/04/28
Raw View
In article <3725C0C2.3B36@eae.com>,
  neppert.gernot@eae.com wrote:
>
> > This is a logical proof that the standard *COULD* have made this legal.
> > There would probably be additional overhead, but not much more.
> > However, the standard *DOES NOT* in fact allow this. From 5.3.5:
> >
> >    1  The delete-expression operator destroys a most-derived object (1.8)
> >       or array created by a new-expression.
> >          delete-expression:
> >             ::opt delete cast-expression
> >             ::opt delete [ ] cast-expression
> >       The first alternative is for non-array objects, and the second is
> >       for arrays. ...[snip]...
> >
> >    3  In the first alternative (delete object), if the static type of
> >       the object is different from it's dynamic type, the static type
> >       shall be a base class of the operator'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.
> >
>
> OK, it may not be LEGAL. This seems to be the wrong newsgroup to answer
> the original question. I just don't get it why all the answers in this
> thread tend to look at vtables, (virtual) destructors etc.
> Remember: The poster merely asked whether deallocation would be handled
> properly if he executed the statements
>
> int* pInt = new int;
> delete (void*)pInt;

And the answer is: the standard says undefined behavior.

> >Sorry. This will work in most cases, but it simply isn't standard.
>
> If you take a look at what the standard says about the default
> implementations of operator new( size_t sz ) and operator delete( void*
> ) - and these are the only functions involved here - you'll find that
> delete shall behave as follows:
> "For such a non-null value of ptr, reclaims storage allocated by the
> earlier call to the default operator new."
>
> So this should really work in any case.

It is very likely to work.  The requirements you state place serious
constraints on the implementation, constraints which mean that the
implementation would have to work for it not to work.  Especially since
the sequence:

    void* tmp = pInt ;
    pInt->~int() ;
    operator delete( tmp ) ;

is guaranteed to work.  (And of course, in this particular case, the
second line is a no-op, and can be deleted).

On the other hand, the utility of this information is limited, since the
above analogy fails as soon as the object is an array or is not a POD.

--
James Kanze                         mailto: James.Kanze@dresdner-bank.com
Conseils en informatique orient   e objet/
                        Beratung in objekt orientierter Datenverarbeitung
Ziegelh   ttenweg 17a, 60598 Frankfurt, Germany  Tel. +49 (069) 63 19 86 27

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Ewert_Ahr._Electronic_GmbH@t-online.de (Gernot)
Date: 1999/04/23
Raw View
AllanW {formerly AllanW@my-dejanews.com} wrote:
>
> In article <aVTR2.738$Ey4.584@news.rdc1.tx.home.com>,
>   "Brandon Jackson" <erreichbar@hotmail.com> wrote:
> > Hello there,
> >
> > I've got a rather interesting question about "new" and "delete".
> >
> > Question:  Will "delete" handle deallocation properly if the following code
> > were used
> >
> > int * pInt;
> > pInt = new int;
> >
> > delete (reinterpret_cast<void *> (pInt));
>
> This is not valid C++.
>
> As a practical matter, it should work correctly on most platforms
> provided that the data (in this case an int) does not have a destructor.
> But seeing as how you asked the question in a newsgroup about standards,
> no, this is clearly NOT legal.
>

I think this is perfectly legal. The poster was asking about different
builtin types, not arbitrary (class) types.

1. All builtin types do not need a destructor call.

2. You cannot overload the new/delete operator differently for different
builtin types.

3. The standard 1-argugment global delete operator does not get any
information about object size, so it must handle deallocation by itself
anyway.

Conclusion:

For any two given builtin types T1, T2 the following code is legal:

T1* p = new T1;
delete (T2*)p;
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@bardeen.ceg.uiuc.edu (Siemel Naran)
Date: 1999/04/24
Raw View
On 23 Apr 99 22:14:24 GMT, Gernot

>Conclusion:
>
>For any two given builtin types T1, T2 the following code is legal:
>
>T1* p = new T1;
>delete (T2*)p;

It appears so.  I found to my dismay that the following program compiles
and runs on egcs.  The destructor T::~T() is not called.


#include <iostream.h>

struct T { virtual ~T(){cout<<"T dtor\n";} };

int main()
{
   T * i = new T();
   void * v = i;
   delete v; // IMHO, this should be an error!
}


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Jim Hyslop <jim.hyslop@leitch.com>
Date: 1999/04/24
Raw View
In article <aVTR2.738$Ey4.584@news.rdc1.tx.home.com>,
  "Brandon Jackson" <erreichbar@hotmail.com> wrote:
> Hello there,
>
> I've got a rather interesting question about "new" and "delete".
>
> Question:  Will "delete" handle deallocation properly if the following code
> were used
>
> int * pInt;
> pInt = new int;
>
> delete (reinterpret_cast<void *> (pInt));
>
> This question does have a basis in standard C++ programming, but my
> motivation for this question comes out of programming for Win32.  Often I've
> found it necessary to have a data type casted to squeeze it into some API
> callback function and then cast it back to it's original type for use in the
> callback function.
The code that you have posted does not match the description in your above
paragraph.

What you have described is:
// someapi.h
typedef void (*CALLBACK)(void *);
someAPIFunction(void *, CALLBACK);

// Yourfile.cpp
#include <someapi.h>

void releasePointer(void *p)
{
   delete reinterpret_cast<int *>(p);
}

void aFunction()
{
   int *ptr=new int;
   someAPIFunction(ptr, releasePointer);
}

In this case, you are simply restoring the original type of the variable, and
all should work just fine (providing a 'void *' is at least as big as an 'int
*', which it is in Win32).

--
Jim
I ignore all email from recruitment agencies.
Please do not send me email with questions - post here.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Valentin Bonnard <Bonnard.V@wanadoo.fr>
Date: 1999/04/25
Raw View
Jim Hyslop wrote:

> void releasePointer(void *p)
> {
>    delete reinterpret_cast<int *>(p);
> }
>
> void aFunction()
> {
>    int *ptr=new int;
>    someAPIFunction(ptr, releasePointer);
> }
>
> In this case, you are simply restoring the original type of the variable, and
> all should work just fine (providing a 'void *' is at least as big as an 'int
> *', which it is in Win32).

It is, that's precisely the purpose of void*. By the way, you should
use static_cast, as you are really casting back to a derived type
(assuming every type is derived from void (a natural view of things)).

--

Valentin Bonnard
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1999/04/25
Raw View
In article <slrn7i1tvo.6qt.sbnaran@bardeen.ceg.uiuc.edu>,
sbnaran@bardeen.ceg.uiuc.edu says...

[ ... ]

> int main()
> {
>    T * i = new T();
>    void * v = i;
>    delete v; // IMHO, this should be an error!
> }

Assuming T has at least one virtual member, why couldn't the run-time
system figure out its real type, and delete it correctly?  It has to
have the information about its real type available when/if you attempt
to do a dynamic_cast, and that information _should_ be sufficient to
let it delete the object correctly as well, shouldn't it?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "AllanW {formerly AllanW@my-dejanews.com}" <allan_w@my-dejanews.com>
Date: 1999/04/22
Raw View
In article <aVTR2.738$Ey4.584@news.rdc1.tx.home.com>,
  "Brandon Jackson" <erreichbar@hotmail.com> wrote:
> Hello there,
>
> I've got a rather interesting question about "new" and "delete".
>
> Question:  Will "delete" handle deallocation properly if the following code
> were used
>
> int * pInt;
> pInt = new int;
>
> delete (reinterpret_cast<void *> (pInt));

This is not valid C++.

As a practical matter, it should work correctly on most platforms
provided that the data (in this case an int) does not have a destructor.
But seeing as how you asked the question in a newsgroup about standards,
no, this is clearly NOT legal.

----
Allan_W@my-dejanews.com is a "Spam Magnet" -- never read.
Please reply in USENET only, sorry.

-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: David R Tribble <dtribble@technologist.com>
Date: 1999/04/20
Raw View
Brandon Jackson wrote:
>> Question:  Will "delete" handle deallocation properly if the
>> following code were used
>>
>>    int * pInt;
>>    pInt = new int;
>>
>>    delete (reinterpret_cast<void *> (pInt));

James Kuyper wrote:
> Section 5.3.5 p3: says about the delete-expression that: "If the
> static type of the operand is different from its dynamic type, the
> static type shall be be a base class of the operand's dynamic type and
> the static type shall have a virtual destructor, or the behaviour is
> undefined."
>
> Footnote 73) points out that this means that the object cannot be
> deleted using a 'void *' pointer, because there are no objects of type
> void.
> The reason for this is simple - how whould it know which destructor to
> call? For that matter, how would it know whether or not to call a
> class-specific operator delete(), and which one?

>>
>> This question does have a basis in standard C++ programming, but my
>> motivation for this question comes out of programming for Win32.
>> Often I've found it necessary to have a data type casted to squeeze
>> it into some API callback function and then cast it back to its
>> original type for use in the callback function.

It would probably be better to dynamic_cast the pointer to a base
class type, so that the proper virtual destructor gets called.
This implies that all the objects you do this sort of thing to
ought to inherit from one (or a few) base class type.

As pointed out above, casting to void* removes all useful information
about the pointed-to object.

-- David R. Tribble, dtribble@technologist.com --


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1999/04/19
Raw View
In article <aVTR2.738$Ey4.584@news.rdc1.tx.home.com>, Brandon Jackson
<erreichbar@hotmail.com> writes
>Hello there,
>
>I've got a rather interesting question about "new" and "delete".
>
>Question:  Will "delete" handle deallocation properly if the following code
>were used
>
>int * pInt;
>pInt = new int;
>
>delete (reinterpret_cast<void *> (pInt));
>

I can see no reason why you might get a problem in real code, as long as
the true type has only a trivial dtor.  In such circumstances delete
only needs to release memory.  This is not a matter of intelligence,
just a matter of what deleting a void * is required to do.


>This question does have a basis in standard C++ programming, but my
>motivation for this question comes out of programming for Win32.  Often I've
>found it necessary to have a data type casted to squeeze it into some API
>callback function and then cast it back to it's original type for use in the
>callback function.

Francis Glassborow      Journal Editor, Association of C & C++ Users
64 Southfield Rd
Oxford OX4 1PA          +44(0)1865 246490
All opinions are mine and do not represent those of any organisation
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Brandon Jackson" <erreichbar@hotmail.com>
Date: 1999/04/18
Raw View
Hello there,

I've got a rather interesting question about "new" and "delete".

Question:  Will "delete" handle deallocation properly if the following code
were used

int * pInt;
pInt = new int;

delete (reinterpret_cast<void *> (pInt));

This question does have a basis in standard C++ programming, but my
motivation for this question comes out of programming for Win32.  Often I've
found it necessary to have a data type casted to squeeze it into some API
callback function and then cast it back to it's original type for use in the
callback function.

I really appreciate any information anyone can send me on this issue.

Thank you,

- Brandon
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Al Cilcius" <alcilcius@3rdsigma.com>
Date: 1999/04/19
Raw View
Yes, the deallocation will be handled correctly.  However, the destructor
(if any) called is dependant on what the type of the pointer is, NOT on what
is actually resident at that memory location.  For instance:
    CFoo* pFoo = new CFoo;
    delete reinterpret_cast<void*>(pFoo);
will indeed deallocate the memory at location pFoo, by ~CFoo will NOT be
called.

Brandon Jackson <erreichbar@hotmail.com> wrote in message
news:aVTR2.738$Ey4.584@news.rdc1.tx.home.com...
> Hello there,
>
> I've got a rather interesting question about "new" and "delete".
>
> Question:  Will "delete" handle deallocation properly if the following
code
> were used
>
> int * pInt;
> pInt = new int;
>
> delete (reinterpret_cast<void *> (pInt));
>
> This question does have a basis in standard C++ programming, but my
> motivation for this question comes out of programming for Win32.  Often
I've
> found it necessary to have a data type casted to squeeze it into some API
> callback function and then cast it back to it's original type for use in
the
> callback function.
>
> I really appreciate any information anyone can send me on this issue.
>
> Thank you,
>
> - Brandon
> ---
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James Kuyper <kuyper@wizard.net>
Date: 1999/04/19
Raw View
Brandon Jackson wrote:
>
> Hello there,
>
> I've got a rather interesting question about "new" and "delete".
>
> Question:  Will "delete" handle deallocation properly if the following code
> were used
>
> int * pInt;
> pInt = new int;
>
> delete (reinterpret_cast<void *> (pInt));
>
> This question does have a basis in standard C++ programming, but my
> motivation for this question comes out of programming for Win32.  Often I've
> found it necessary to have a data type casted to squeeze it into some API
> callback function and then cast it back to it's original type for use in the
> callback function.
>
> I really appreciate any information anyone can send me on this issue.

Section 5.3.5 p3: says about the delete-expression that: "If the static
type of the operand is different from its dynamic type, the static type
shall be be a base class of the operand's dynamic type and the static
type shall have a virtual destructor, or the behaviour is undefined."

Footnote 73) points out that this means that the object cannot be
deleted using a 'void *' pointer, because there are no objects of type
void.
The reason for this is simple - how whould it know which destructor to
call? For that matter, how would it know whether or not to call a
class-specific operator delete(), and which one?
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@localhost.localdomain (Siemel Naran)
Date: 1999/04/19
Raw View
On 18 Apr 99 13:19:43 GMT, Brandon Jackson <erreichbar@hotmail.com> wrote:

>Question:  Will "delete" handle deallocation properly if the following code
>were used
>
>int * pInt;
>pInt = new int;
>
>delete (reinterpret_cast<void *> (pInt));

I'd use "static_cast" instead.

But it doesn't work.  The compiler does not know which destructor
should call.  If every object derived from class void and
void::~void() were virtual, then it would work.  But really...

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1999/04/19
Raw View
"Brandon Jackson" <erreichbar@hotmail.com> writes:

> delete (reinterpret_cast<void *> (pInt));

This is not required to work. [expr.delete]/3 says

>> 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 your example, the static and the dynamic type are different, but
'void' is not a base type of 'int'. The compiler could even warn about
this code: Deleting a void* would assume that the object behind the
pointer is of type 'void' - there are no such objects in C++.

Hope this helps,
Martin
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]