Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017 
<== Date ==> <== Thread ==>

Subject: Re: mallocMustSucceed( 0 ) non-portable
From: Andrew Johnson <anj@aps.anl.gov>
To: Michael Abbott <michael.abbott@diamond.ac.uk>
Cc: EPICS Tech-Talk <tech-talk@aps.anl.gov>
Date: Tue, 31 Jan 2006 14:42:38 -0600
Michael Abbott wrote:
Of course this means that callocMustSucceed and mallocMustSucceed can return a NULL pointer, which they currently never do.....

That's the dilemma. I thought about that but I believe requesting zero-sized memory and subsequent de-referencing the return value can be considered a programming error. Otherwise, I can't see how to avoid a memory leak.

Makes sense to me. After all, what can you legally do with char * x = malloc(0); ?

I understand that position, however I really don't like it.


The ?allocMustSucceed() routines were always a bit of a hack to avoid having to check the return value from ?alloc. They are only called in dbStaticLib and the IOC startup code in places where if you run out of memory there's no way you're going to be able to recover and still bring up the IOC, so the only thing you can do is bail out.

They do that by printing an error message and suspending the task, thus ensuring that the caller never gets a chance to continue processing. The task suspend is to allow a developer to do a back-trace on the task that failed and thus find the rogue code, in the event that the problem is being caused by a bug rather than a lack of RAM.

As an aside, many of the blocks allocated through these routines don't have an associated call to free() at all, thus wondering whether they'll result in a memory leak is a rather futile thing anyway.

I view any attempt to use these routines to allocate a zero-sized object as a bug, and as such it should result in the same task suspension that happens if you run out of memory. This is probably the fastest way to ensure that any such bug gets fixed...

Here's the implementation I'm planning to commit, which should now be completely portable (calloc is similar, checking both count and size):

void * mallocMustSucceed(size_t size, const char *errorMessage)
{
    void * mem = NULL;
    if (size != 0)
        mem = malloc(size);
    if (mem == NULL) {
        errlogPrintf("%s: mallocMustSucceed(size=%lu) failed\n",
            errorMessage, (unsigned long)size);
        cantProceed(0);
    }
    return mem;
}

- Andrew
--
* * Matt Santos / / For a Brighter America * *

Replies:
Re: mallocMustSucceed( 0 ) non-portable Benjamin Franksen
References:
mallocMustSucceed( 0 ) non-portable Till Straumann
Re: mallocMustSucceed( 0 ) non-portable Eric Norum
Re: mallocMustSucceed( 0 ) non-portable Till Straumann
Re: mallocMustSucceed( 0 ) non-portable Michael Abbott

Navigate by Date:
Prev: Re: mallocMustSucceed( 0 ) non-portable Michael Abbott
Next: how to determine record type given pointer to a record John Dobbins
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017 
Navigate by Thread:
Prev: Re: mallocMustSucceed( 0 ) non-portable Michael Abbott
Next: Re: mallocMustSucceed( 0 ) non-portable Benjamin Franksen
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  <20062007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017 
ANJ, 02 Sep 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·