Memory leak in ev.c, the second

Marc Lehmann schmorp at
Thu Feb 21 16:01:08 CET 2013

On Thu, Feb 21, 2013 at 10:39:20AM +0100, Alexander Klauer <Alexander.Klauer at> wrote:
> 1. if size is equal to zero, and ptr is
> not NULL, then the call is equivalent to free(ptr)."
> The last assertion is incorrect. See 4. for a proof on concept in
> libev below.

That assertion was correct until reletively recently. In response to
glibc breaking this documented behaviour, libev added a workaround.

> 2. The C89 standard says "If the size of the space requested is zero,
> the behavior is implementation-defined;

The C89 standard says (any typos are mine): the realloc function


   If size is zero and ptr is not a null pointer, the object it points to is

Your quote is from 7.10.3, and only applies if an allocation is actually
requested ("If the size of the space requested..."), which isn't the case
for the case above.

If you want to argue that the ISO-C requirement "the object it points to
is freed" does not mean free(ptr) or an equivalent is called then we will
have to disagree.

> either a null pointer or a unique pointer." The realloc() shipped
> with glibc 2.15 is C89-compliant, taking the second choice.

Cannot be true - either the behaviour is as you say or it is c89
compliant, it can't be both.

> particular, a realloc(ptr, 0) does all that which free(ptr) does, but
> it does something on top: every such call returns a unique non-null
> pointer, which may later be safely passed to free().

There is nothing in C89 allowing this behaviour. I agree that the wording
is not optimal (which is why implementations might differ), and this is
why the wording has changed, but the austin group still thinks the C99
wording is not good enough. I don't know about later changes.

> However, the C library must keep some internalinformation as to which
> pointers may be passed to free(), and it's that information which takes
> upmemory.

I have no clue what you mean with that, but since realloc free's, and no
allocation of space is requested, any internal bookkeeping information is by
definition not needed.

(It's also not needed for 0 pointers btw.)

> 3. The libev default allocator in the current CVS head does the right
> thing bycalling free() when the passed size is zero. However, the
> libev documentation says that the allocator merely has to have
> "semantics [...] identical to the |realloc| C89/SuS/POSIX function"
> which is not enough.

It is, and both POSIX and the C standards commitees agree with this (see
POSIX defect report 400, among others).

> (minor nit: C89 realloc()'s second parameter has type size_t while
> the libev allocator expects a long)

You are confusing prototype with semantics.

> 4. I have attached a proof of concept demonstrating the problem. The
> attached program effectively replaces the libev standard allocator
> with realloc().

What exactly do you think that proves? The actual (new) behaviour of
glibc's realloc is not something we disagree about, and is something that
libev takes into account.

> I hope this postclarifies the issue.

Yes, apparently, your confusion comes from an incorrect interpretation of
C89. The documentation of libev does point out that using realloc directly
is not portable.

It is unfortunate that glibc has broken this behaviour, but strictly
speaking, glibc has introduced the memleak you might be seeing with libev
(or your example program), and libev has added a workaround for it.

                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_    
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      schmorp at
      -=====/_/_//_/\_,_/ /_/\_\

More information about the libev mailing list