From 4070761881167138685
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: f78e5,ba46df2c00e31ceb
X-Google-Attributes: gidf78e5,public
X-Google-ArrivalTime: 2004-02-29 09:00:02 PST
Return-Path: <devnull@stump.algebra.com>
X-Authentication-Warning: mulga.cs.mu.OZ.AU: fjh set sender to devnull@stump.algebra.com using -f
Path: archiver1.google.com!news2.google.com!news.maxwell.syr.edu!cyclone.bc.net!news.alt.net!comp-std-cpp-robomod!not-for-mail
X-Robomod: STUMP, ichudov@algebra.com (Igor Chudov)
Delivered-To: std-c++@ucar.edu
From: Graeme Prentice <invalid@yahoo.co.nz>
Newsgroups: comp.std.c++
Subject: Re: Why no size_t in global operator delete?
Message-ID: <dff240hh8i7lbpe9q87a55o0jis3nn8u26@4ax.com>
References: <MPG.1aa86999b63db146989733@news.hevanet.com> <2bbfa355.0402270546.4e45f5a9@posting.google.com>
Reply-To: gprenz@hotmail.com
X-Orig-NNTP-Posting-Host: 203-96-146-235.apx1.paradise.net.nz (203.96.146.235)
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Orig-X-Trace: news.uni-berlin.de 1078017898 56570550 I 203.96.146.235 ([98036])
X-Newsreader: Forte Agent 1.93/32.576 English (American)
X-Spam-Checker-Version: SpamAssassin 2.60-mulga_r1 (1.212-2003-09-23-exp) on 
	mulga.cs.mu.OZ.AU
X-Spam-Status: No, hits=0.0 required=5.2 tests=none autolearn=no 
	version=2.60-mulga_r1
Approved: Fergus Henderson <fjh@cs.mu.oz.au>, moderator of comp.std.c++
Date: Sun, 29 Feb 2004 10:57:45 CST
Lines: 114
Xref: archiver1.google.com comp.std.c++:1249

On Fri, 27 Feb 2004 17:39:45 CST, Bill Wade wrote:

>Scott Meyers <Usenet@aristeia.com> wrote in message news:<MPG.1aa86999b63db146989733@news.hevanet.com>...
>> Classes can declare an operator delete that has the runtime system provide
>> the size of the just-destructed-object whose memory is being deallocated:
>> 
>>   void operator delete(void *ptr, size_t sizeOfFormerObject);
>> 
>> Does anybody know why there is no global operator delete with this same
>> signature?  [...]  Is there a good technical basis for the omission?
>
>The language allows delete to occur at a point where the type is
>incomplete (and with separate compilation, the size is not known). 
>One could argue about whether or not this is a "good" language
>feature.  Asking the runtime to remember the size in this case costs
>something, even when it isn't needed.

The type being deleted can be incomplete only if it has a trivial
destructor (i.e. it's not user written and its members and bases all
have trivial destructors) and no deallocation functions (member operator
delete functions).  The runtime wouldn't have to remember the size - if
the class was incomplete, it could call __get_size_for_class_blah_blah
which the compiler provided for all classes with trivial destructors and
the linker removed any that weren't called.  Possibly it wouldn't even
need to call a function - it could just access a constant
__size_of_class_blah_blah that the linker was able to find and "fix up".

Classes with non trivial destructors have to be complete so that the
compiler can actually call the destructor  - even this could probably be
worked around by a call to __destroy_pointer_to_class_blah_blah if the
class was incomplete, but you would have a wasted function call for
incomplete classes with a trivial destructor. (similarly for the member
operator delete situation).


>
>In practice, a user-written global new/delete will frequently be
>written in terms of malloc()/free(), and free() does not need to be
>"told" the size.

If you're writing a memory pool such as the small object allocator in
Loki, the size of the block being deleted is useful.  In Loki's case,
the size value is used to do a binary search through a vector, to find
the specific memory pool for objects of that size.  Blocks of memory
returned by the Loki small object allocator can be as small as one byte
(and there is no additional overhead for that one object) - the size of
an object is never actually stored in dynamic memory anywhere, as it is
with malloc/free.


>
>If you want to see see the size at dealloc time, and don't want to use
>class::new/delete, you might consider using the std::allocator
>interface.  However, it does put more restrictions on the client code.

How would that work?  

Suppose we try to write a version of delete that could be called  e.g.
my_delete( some_pointer )  - how would we write my_delete?

template <typename T>
void my_delete( T * ptr )
{
	ptr->T::~T();   // not all compilers like this
      std::cout << "\nmy_delete called. " << sizeof (T);
}

If ptr points to an object derived from T, there's no way to get the
correct size without compiler help or a user written get_size() virtual
function - in which case it's less work to provide the two parameter
operator delete in the base class, and doesn't require remembering to
call my_delete instead of delete.

The language could define that if the user supplied a two parameter
global delete function
void operator delete( void *, size_t );

then calls to delete myptr results in a call to the two parameter
version instead of the one parameter version.  This would save having to
define a two parameter operator delete for all classes.  It's not hard
for the compiler to supply the correct size for polymorphic objects  -
Andrei Alexandrescu suggested four methods of how it can be done in his
book.  

Explicit calls to the one parameter global operator delete, as in the
default allocator, would still call the one parameter version, which
would be a problem if the global operator new had been user defined, and
is probably one reason why the global two parameter operator delete
isn't allowed.  Explicit calls to the global one parameter delete could
be made illegal if a two parameter delete was declared though, and as
Josuttis says, writing your own allocator is not hard...   but as Roger
Orr said, this is problematic at the global level   e.g. there could be
explicit calls to the one parameter operator delete from a variety of
places, so it could get messy.  How do you ensure that all memory
allocated from a call to a user written global operator new, gets
deallocated by a call to the corresponding user written global operator
delete  - perhaps the system could guarantee it by forcing all calls to
global delete, to the user written one.

Stroustrup says replacing the global operator new and delete is not for
the fainthearted (15.6 freestore) and points out that other code might
rely on some aspect of the default behaviour or might want to supply
their own version of global new/delete  - i.e. a recipe for conflict.

If I'm wrong, which I could be, it ain't gonna matter.

Graeme

---
[ 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://www.jamesd.demon.co.uk/csc/faq.html                       ]



