public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* malloc/free & new/delete balance
@ 1998-06-29  8:41 Carlo Wood
  1998-06-30  1:02 ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Carlo Wood @ 1998-06-29  8:41 UTC (permalink / raw)
  To: egcs

In gcc/cp/new2.cc,

WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc))
{
  return ::operator new(sz);
}

...

WEAK (void operator delete[] (void *ptr) throw ())
{
  if (ptr)
    free (ptr);
}

This unbalance between calling `::operator new(size_t)' and `free(void *)'
is causing troubles when `operator new(size_t)' and `operator delete(void *)'
are overloaded [ for example to call special memory allocation/deallocation
functions called malloc_with_prepended_magic_number(size_t) and
free_with_prepended_magic_number(void *). Then calling 'operator
new[](size_t)' uses malloc_with_prepended_magic_number(size_t) and
'operator delete[](void *)' uses just free(void *) ].

The way it is now you force people to also overload operator new[] and
operator delete[] when they overloaded operator new and operator delete.

Imho, the only correct way is to balance this and use:

WEAK (void operator delete[] (void *ptr) throw ())
{
  ::operator delete(ptr);
}

Alternatively, and probably a little faster, is to duplicate the
code from operator new(size_t) and use:

WEAK(void * operator new[] (size_t sz) throw (std::bad_alloc))
{
  /*
   * This is an exact copy of
   * void * operator new (size_t sz) throw (std::bad_alloc)
   */

  void *p;

  /* malloc (0) is unpredictable; avoid it.  */
  if (sz == 0)
    sz = 1;
  p = (void *) malloc (sz);
  while (p == 0)
    {
      new_handler handler = __new_handler;
      if (! handler)
        throw bad_alloc ();
      handler ();
      p = (void *) malloc (sz);
    }

  return p;
}

Comments?

-- 
 Carlo Wood  <carlo@runaway.xs4all.nl>

^ permalink raw reply	[flat|nested] 13+ messages in thread
* Re: malloc/free & new/delete balance
@ 1998-06-30 14:46 Sol Foster
  0 siblings, 0 replies; 13+ messages in thread
From: Sol Foster @ 1998-06-30 14:46 UTC (permalink / raw)
  To: egcs

Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
> 
> Carlo Wood <carlo@runaway.xs4all.nl> writes:
> 
> > WEAK (void operator delete[] (void *ptr) throw ())
> > {
> >   if (ptr)
> >     free (ptr);
> > }
> 
> > This unbalance between calling `::operator new(size_t)' and `free(void *)'
> > is causing troubles when `operator new(size_t)' and `operator delete(void *)'
> > are overloaded
> 
> Agreed, but, for some reason, the FDIS [lib.new.delete.array] defines
> operator new[](size_t) as returning operator new(size_t) by default,
> while it states that operator delete[](void*) frees the pointer it is
> given.  

Huh?  It's correct in the Nov'96 paper.  "For such a non-null value of
ptr, reclaims storage allocated by the earlier call to the default
operator new[]."  Nothing about free in there.  You mean they changed it
to something obviously incorrect?  *None* of the deletes should be defined
in terms of free...  (Implemented, sure, but not defined.)

> So, I'd say the implementation is correct, and calling operator
> delete(void*) is non-standard.  Too bad. :-(

While it isn't that hard to get around (just replace the all operators 
with your own) it seems a shame to allow an obvious mistake like this into
EGCS.


-- 
Sol Foster: colomon@ralf.org

A genius is someone who travels to truth by an unexpected path.
Unfortunately, unexpected paths lead to disaster in everyday life.  
                                        -Alfred Bester

^ permalink raw reply	[flat|nested] 13+ messages in thread
* Re: malloc/free & new/delete balance
@ 1998-07-01 22:54 Mike Stump
  1998-07-02  1:39 ` Alexandre Oliva
  0 siblings, 1 reply; 13+ messages in thread
From: Mike Stump @ 1998-07-01 22:54 UTC (permalink / raw)
  To: carlo, oliva; +Cc: egcs

> To: Carlo Wood <carlo@runaway.xs4all.nl>
> Cc: egcs@cygnus.com (egcs@cygnus.com)
> From: Alexandre Oliva <oliva@dcc.unicamp.br>
> Date: 29 Jun 1998 21:54:36 -0300

> > This unbalance between calling `::operator new(size_t)' and
> > `free(void *)' is causing troubles when `operator new(size_t)' and
> > `operator delete(void *)' are overloaded

> Agreed, but, for some reason, the FDIS [lib.new.delete.array]
> defines operator new[](size_t) as returning operator new(size_t) by
> default, while it states that operator delete[](void*) frees

Can you provide an exact quote of this?  I can't find it.  I'll quote
from the FDIS below.

> the pointer it is given.  So, I'd say the implementation is correct,
> and calling operator delete(void*) is non-standard.  Too bad. :-(

The next stage of your learning is to be able to say when the standard
is wrong.  :-)

Also, I think we are staring at different papers.  Does yours have the
number 14882 or X3J16/97-0079 on it?  If not, that isn't the FDIS, and
you should not call it that.

From the real FDIS:

void operator delete[](void* ptr) throw();
void operator delete[](void* ptr, const std::nothrow_t&) throw();

-9- Effects: The deallocation function
 (basic.stc.dynamic.deallocation) called by the array form of a
 delete-expression to render the value of ptr invalid.

-10- Replaceable: a C++ program can define a function with this
 function signature that displaces the default version defined by the
 C++ Standard library.

-11- Required behavior: accept a value of ptr that is null or that was
returned by an earlier call to operator new[](std::size_t) or operator
new[](std::size_t,const std::nothrow_t&).

-12- Default behavior: 

       For a null value of ptr , does nothing. 

       Any other value of ptr shall be a value returned earlier by a
       call to the default operator new[](std::size_t).*

              [Footnote: The value must not have been invalidated by
              an intervening call to operator delete[](void*)
              (lib.res.on.arguments). --- end foonote]

       For such a non-null value of ptr , reclaims storage allocated
       by the earlier call to the default operator new[].

-13- It is unspecified under what conditions part or all of such
reclaimed storage is allocated by a subsequent call to operator new or
any of calloc, malloc, or realloc, declared in <cstdlib>.


Note the word above, ``reclaims.''  The calls should be symmetric as
one would guess without reading the standard.  In fact, it is a bug
that the standard doesn't refine the language and say exactly that it
must call delete.

^ permalink raw reply	[flat|nested] 13+ messages in thread
* Re: malloc/free & new/delete balance
@ 1998-07-03  7:20 Sol Foster
  1998-07-03 19:30 ` Carlo Wood
  0 siblings, 1 reply; 13+ messages in thread
From: Sol Foster @ 1998-07-03  7:20 UTC (permalink / raw)
  To: egcs

Alexandre Oliva <oliva@dcc.unicamp.br> wrote:
> I didn't write delete[] calls free(), I just said it frees
> (deallocates) the memory.  No where it says delete[] calls delete by
> default, and, since it does for new[] and new, I took it as a
> difference, rather than as an omission.

I'd argue it's strongly implied that, if the memory is allocated with new,
then it is deallocated with delete.  It's disappointing that the standard
doesn't specify this, but then, it doesn't even specify that the memory is
actually given back to the heap.  (At least, that's my reading, and
Plauger seems to agree: "It is unspecified under what conditions part or
all of such reclaimed storage is allocated by a subsequent call to
operator new(size_t), or to any of calloc(size_t), malloc(size_t),
or realloc(void*, size_t).")

Can anyone think of any reasons other than these to use free?

1) delete just calls free anyway, so this saves a function call.

2) The standard doesn't absolutely specify using delete, so standard
conforming programs must replace new[] and delete[] if they replace new
and delete.  Therefore we should introduce hideous bugs into their code if
they don't comply.

Is the extra function call that much more expensive than what free does
internally?  



-- 
Sol Foster: colomon@ralf.org

If you pick up a starving dog and make him prosperous, he will not
bite you. This is the principal difference between a dog and a man. 
                                        -Mark Twain

^ permalink raw reply	[flat|nested] 13+ messages in thread
[parent not found: <199807031202.IAA26419.cygnus.egcs@maniac.deathstar.org>]

end of thread, other threads:[~1998-07-07  1:12 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1998-06-29  8:41 malloc/free & new/delete balance Carlo Wood
1998-06-30  1:02 ` Alexandre Oliva
1998-06-30 15:15   ` Carlo Wood
1998-06-30 14:46     ` Alexandre Oliva
1998-06-30 14:46 Sol Foster
1998-07-01 22:54 Mike Stump
1998-07-02  1:39 ` Alexandre Oliva
1998-07-03  7:20 Sol Foster
1998-07-03 19:30 ` Carlo Wood
     [not found] <199807031202.IAA26419.cygnus.egcs@maniac.deathstar.org>
1998-07-05 19:46 ` Nathan Myers
1998-07-06 14:48   ` Joern Rennecke
1998-07-06 18:52     ` John Carr
1998-07-07  1:12       ` Joern Rennecke

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).