On Sun, Dec 16, 2012 at 11:45:37AM -0600, Derek Martin wrote:
I noticed something curious while looking at a bit of Mutt code...
The macro FREE() is redundant: it's defined to safe_free(), which
has exactly the same interface, and which itself has two

IIRC, FREE(x) used to be defined as safe_free(&(x)). It was just a shortcut to avoid having to remember to pass a pointer-to-a-pointer.

implementations.  One is in lib.c, the other in rfc822.c.  They are

The rfc822c.c file was originally designed to be self sufficient, such that it could be reused in other projects. I'm not sure if this is the case any longer.

different, but similar.  The lib.c implementation is this:

void safe_free (void *ptr)      /* __SAFE_FREE_CHECKED__ */
{
 void **p = (void **)ptr;
 if (*p)
 {
   free (*p);                          /* __MEM_CHECKED__ */
   *p = 0;
 }
}


Is there any specific reason the implementation was written thusly?
Granted, this is a pretty minor issue...  But still, this all seems
kind of gross.  First, there really ought to be one implementation.
Second, the above implementation has some redundancies:

- It requires a function call

It has been awhile since I've done any performance testing of Mutt, but the overhead involved here was not significant.

- Calling free(NULL) is a noop--perfectly safe (at least since ANSI
  C, I don't have a copy of K&R handy)

I don't remember the reason for this. Back in 1995 when I started writing it I'm not sure that all target platforms had ANSI C support.

- the extra cast seems silly; ptr is required to be **ptr, it should
  be declared that way.

I'm not much of a fan of function-like macros in general, but this
case seems like exactly when you'd want to use one.  I think this
should be replaced with:

#define FREE(x)\
        free((x));\
        x = NULL

It should be free(*(x)), since a ** is passed. And if you want to avoid a function, you need to make sure it can be called in and if- or else- block without the braces, like this:

#define FREE(x)\
        do { free(*(x)); *x = NULL } while(0)

At this point you may well just consider using an inlined function.


me

Reply via email to