Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #26252 > unrolled thread

Failing Malloc

Started byEric <nospam@nospam.com>
First post2012-09-12 20:07 +0000
Last post2012-09-13 00:14 -0700
Articles 20 on this page of 36 — 18 participants

Back to article view | Back to comp.lang.c


Contents

  Failing Malloc Eric <nospam@nospam.com> - 2012-09-12 20:07 +0000
    Re: Failing Malloc Xavier Roche <xroche@free.fr.NOSPAM.invalid> - 2012-09-12 22:12 +0200
      Re: Failing Malloc William Ahern <william@wilbur.25thandClement.com> - 2012-09-12 14:25 -0700
    Re: Failing Malloc Andrew Cooper <andrew@nospam.example.com> - 2012-09-12 21:21 +0100
      Re: Failing Malloc Eric <nospam@nospam.com> - 2012-09-12 20:34 +0000
        Re: Failing Malloc Paul N <gw7rib@aol.com> - 2012-09-12 13:46 -0700
          Re: Failing Malloc Eric <nospam@nospam.com> - 2012-09-13 20:21 +0000
            Re: Failing Malloc Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-09-13 17:31 -0400
            Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-13 17:57 -0400
        Re: Failing Malloc John Gordon <gordon@panix.com> - 2012-09-12 20:55 +0000
          Re: Failing Malloc William Ahern <william@wilbur.25thandClement.com> - 2012-09-12 14:33 -0700
          Re: Failing Malloc falk@rahul.net (Edward A. Falk) - 2012-09-13 22:43 +0000
        Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-12 17:37 -0400
        Re: Failing Malloc Johann Klammer <klammerj@NOSPAM.a1.net> - 2012-09-13 08:57 +0200
    Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-12 17:20 -0400
      Re: Failing Malloc Ian Collins <ian-news@hotmail.com> - 2012-09-13 09:27 +1200
        Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-12 17:56 -0400
          Re: Failing Malloc Ian Collins <ian-news@hotmail.com> - 2012-09-13 10:28 +1200
            Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-12 18:57 -0400
              Re: Failing Malloc William Ahern <william@wilbur.25thandClement.com> - 2012-09-12 16:21 -0700
              Re: Failing Malloc Ian Collins <ian-news@hotmail.com> - 2012-09-13 12:07 +1200
                Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-13 13:18 -0400
                  Re: Failing Malloc Ian Collins <ian-news@hotmail.com> - 2012-09-14 07:37 +1200
                    Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-13 16:05 -0400
                      Re: Failing Malloc William Ahern <william@wilbur.25thandClement.com> - 2012-09-13 14:21 -0700
                        Re: Failing Malloc James Kuyper <jameskuyper@verizon.net> - 2012-09-13 17:38 -0400
                    Re: Failing Malloc William Ahern <william@wilbur.25thandClement.com> - 2012-09-13 14:03 -0700
                      Re: Failing Malloc Ian Collins <ian-news@hotmail.com> - 2012-09-15 10:01 +1200
              Re: Failing Malloc Philip Lantz <prl@canterey.us> - 2012-09-14 02:50 -0700
    Re: Failing Malloc Kaz Kylheku <kaz@kylheku.com> - 2012-09-12 21:36 +0000
    Re: Failing Malloc Eric Sosman <esosman@ieee-dot-org.invalid> - 2012-09-12 17:41 -0400
    Re: Failing Malloc Joe Pfeiffer <pfeiffer@cs.nmsu.edu> - 2012-09-12 16:07 -0600
      Re: Failing Malloc "christian.bau" <christian.bau@cbau.wanadoo.co.uk> - 2012-09-12 16:03 -0700
    Re: Failing Malloc Kenneth Brody <kenbrody@spamcop.net> - 2012-09-12 19:24 -0400
    Re: Failing Malloc The Great Firewall of China Blue <chine.bleu@yahoo.com> - 2012-09-12 16:34 -0700
    Re: Failing Malloc Malcolm McLean <malcolm.mclean5@btinternet.com> - 2012-09-13 00:14 -0700

Page 1 of 2  [1] 2  Next page →


#26252 — Failing Malloc

FromEric <nospam@nospam.com>
Date2012-09-12 20:07 +0000
SubjectFailing Malloc
Message-ID<k2qq2i$aba$1@speranza.aioe.org>
Hi What is a good way to respond to a failed Malloc (returns Null)? I do 
not want to call Abort or Exit immediately.

Thanks

[toc] | [next] | [standalone]


#26253

FromXavier Roche <xroche@free.fr.NOSPAM.invalid>
Date2012-09-12 22:12 +0200
Message-ID<k2qqb1$15m$1@news.httrack.net>
In reply to#26252
Le 12/09/2012 22:07, Eric a écrit :
> Hi What is a good way to respond to a failed Malloc (returns Null)? I do 
> not want to call Abort or Exit immediately.

IMHO, except for large allocations, failure to allocate can lead to abort()

In many cases, if you fail to allocate few bytes with malloc(),
continuing is anyway difficult as the next new operator or guard page
stack allocation will also lead to road end.

[toc] | [prev] | [next] | [standalone]


#26264

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2012-09-12 14:25 -0700
Message-ID<58b7i9-q9p.ln1@wilbur.25thandClement.com>
In reply to#26253
Xavier Roche <xroche@free.fr.nospam.invalid> wrote:
> Le 12/09/2012 22:07, Eric a écrit :
> > Hi What is a good way to respond to a failed Malloc (returns Null)? I do 
> > not want to call Abort or Exit immediately.

> IMHO, except for large allocations, failure to allocate can lead to abort()

> In many cases, if you fail to allocate few bytes with malloc(),
> continuing is anyway difficult as the next new operator or guard page
> stack allocation will also lead to road end.

There's no new operator in C, but maybe this was cross posted.

As for stack pages: Outside of a GUI application, I've never seen C code
that required additional memory when a malloc call fails. Invariably the
error condition bubbles up, unwinding the stack. And outside of a simple
command-line tool executing a single discrete operation, bailing on a simple
allocation failure is extremely poor quality of service from a software
application.

Personally, I choose data structures which never require additional memory
during manipulation, such as linked lists or non-recursive trees with nodes
part of the member objects. That means even under memory exhaustion I can
always clean up and return to a steady state.

[toc] | [prev] | [next] | [standalone]


#26254

FromAndrew Cooper <andrew@nospam.example.com>
Date2012-09-12 21:21 +0100
Message-ID<L864s.41309$Ax.33657@fx18.am4>
In reply to#26252
On 12/09/2012 21:07, Eric wrote:
> Hi What is a good way to respond to a failed Malloc (returns Null)? I do 
> not want to call Abort or Exit immediately.
> 
> Thanks
> 

Well - you should probably try to flush any files which are open, return
eternal changes back to defaults (changes to the terminal etc), and find
a way of letting your user see, or at least work out why they no longer
have a running process.

Failing gracefully is a lot more effort than you might imagine at first.

~Andrew

[toc] | [prev] | [next] | [standalone]


#26255

FromEric <nospam@nospam.com>
Date2012-09-12 20:34 +0000
Message-ID<k2qrlc$ea5$1@speranza.aioe.org>
In reply to#26254
On Wed, 12 Sep 2012 21:21:02 +0100, Andrew Cooper wrote:

> On 12/09/2012 21:07, Eric wrote:
>> Hi What is a good way to respond to a failed Malloc (returns Null)? I
>> do not want to call Abort or Exit immediately.
>> 
>> Thanks
>> 
>> 
> Well - you should probably try to flush any files which are open, return
> eternal changes back to defaults (changes to the terminal etc), and find
> a way of letting your user see, or at least work out why they no longer
> have a running process.
> 
> Failing gracefully is a lot more effort than you might imagine at first.

Sorry maybe I wasn't too clear. I would like to get the Malloc call to 
succeed if I redo it. Or get some alternative memory eg from the stack or 
swop.

[toc] | [prev] | [next] | [standalone]


#26257

FromPaul N <gw7rib@aol.com>
Date2012-09-12 13:46 -0700
Message-ID<e95d81dd-908d-42cb-bdd2-893456fe16f3@e29g2000vbm.googlegroups.com>
In reply to#26255
On Sep 12, 9:34 pm, Eric <nos...@nospam.com> wrote:
> On Wed, 12 Sep 2012 21:21:02 +0100, Andrew Cooper wrote:
> > On 12/09/2012 21:07, Eric wrote:
> >> Hi What is a good way to respond to a failed Malloc (returns Null)? I
> >> do not want to call Abort or Exit immediately.
>
> >> Thanks
>
> > Well - you should probably try to flush any files which are open, return
> > eternal changes back to defaults (changes to the terminal etc), and find
> > a way of letting your user see, or at least work out why they no longer
> > have a running process.
>
> > Failing gracefully is a lot more effort than you might imagine at first.
>
> Sorry maybe I wasn't too clear. I would like to get the Malloc call to
> succeed if I redo it. Or get some alternative memory eg from the stack or
> swop.

If your program has an alternative way of working which uses less
memory (say, for example, a slower method) you could put in a new
malloc asking for less memory and see if that works. Or you could
allocate more memory than you need early in the program, so you've got
a bit already to hand when you run a crucial bit of the program. Or
you could tell the user that unfortunately the program can't do what
was requested.

Getting more memory from the stack seems a little risky, as there are
normally less checks whether it worked. Swapping your own program's
data out to disk might be a possibility if you keep track of what you
have done. Swapping other programs out to disk is system-specific, if
you want to try this then other newsgroups will be able to give better
help.

Hope that helps.
Paul.

[toc] | [prev] | [next] | [standalone]


#26310

FromEric <nospam@nospam.com>
Date2012-09-13 20:21 +0000
Message-ID<k2tf88$ki9$1@speranza.aioe.org>
In reply to#26257
On Wed, 12 Sep 2012 13:46:51 -0700, Paul N wrote:
> On Sep 12, 9:34 pm, Eric <nos...@nospam.com> wrote:
>> On Wed, 12 Sep 2012 21:21:02 +0100, Andrew Cooper wrote:
>> > On 12/09/2012 21:07, Eric wrote:
>> >> Hi What is a good way to respond to a failed Malloc (returns Null)?
>> >> I do not want to call Abort or Exit immediately.
>>
>> >> Thanks
>>
>> > Well - you should probably try to flush any files which are open,
>> > return eternal changes back to defaults (changes to the terminal
>> > etc), and find a way of letting your user see, or at least work out
>> > why they no longer have a running process.
>>
>> > Failing gracefully is a lot more effort than you might imagine at
>> > first.
>>
>> Sorry maybe I wasn't too clear. I would like to get the Malloc call to
>> succeed if I redo it. Or get some alternative memory eg from the stack
>> or swop.
> 
> If your program has an alternative way of working which uses less memory
> (say, for example, a slower method) you could put in a new malloc asking
> for less memory and see if that works. Or you could allocate more memory
> than you need early in the program, so you've got a bit already to hand
> when you run a crucial bit of the program. Or you could tell the user
> that unfortunately the program can't do what was requested.
> 
> Getting more memory from the stack seems a little risky, as there are
> normally less checks whether it worked. Swapping your own program's data
> out to disk might be a possibility if you keep track of what you have
> done. Swapping other programs out to disk is system-specific, if you
> want to try this then other newsgroups will be able to give better help.

What I mean is, imagine a very large allocation say 4MB. Maybe that's not 
available in one chunk, however 4 seperate 1MB allocations could succeed. 
That sort of thing.

By stack I mean essentially a local array, i.e.
func()
{
  char buf[1000]; /* <--- example */
  /* buf can never be Null */
}

Note, that in this case, Null can never be returned for the array.

Thanks

[toc] | [prev] | [next] | [standalone]


#26318

FromEric Sosman <esosman@ieee-dot-org.invalid>
Date2012-09-13 17:31 -0400
Message-ID<k2tjc5$244$1@dont-email.me>
In reply to#26310
On 9/13/2012 4:21 PM, Eric wrote:
>[...]
> By stack I mean essentially a local array, i.e.
> func()
> {
>    char buf[1000]; /* <--- example */
>    /* buf can never be Null */
> }
>
> Note, that in this case, Null can never be returned for the array.

     Probably works for 1000 chars, probably works for 10000,
but what if you need 10MB?  Lots of systems devote only a
limited amount of memory for `auto' variables, and if your
program exceeds the limit it's likely to die even more quickly
than if malloc() returned `NULL' (not `Null').  That's what
Paul N meant by "there are normally less checks whether it
worked:" malloc() tells you when it fails and gives you a
choice about how to proceed, but stack explosion doesn't.

     Also, I'm a little worried about that word "returned."  If
you intend to have func() return a pointer to buf[] or any
part of it, you're in deep trouble: buf[] ceases to exist as
soon as func() returns, and if a caller tries to use a pointer
to the non-existent buf[] there will be fertilizer on the fan.

-- 
Eric Sosman
esosman@ieee-dot-org.invalid
"The speed at which the system fails is usually not important."

[toc] | [prev] | [next] | [standalone]


#26321

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-09-13 17:57 -0400
Message-ID<505256DA.80605@verizon.net>
In reply to#26310
On 09/13/2012 04:21 PM, Eric wrote:
> On Wed, 12 Sep 2012 13:46:51 -0700, Paul N wrote:
...
>> If your program has an alternative way of working which uses less memory
>> (say, for example, a slower method) you could put in a new malloc asking
>> for less memory and see if that works. Or you could allocate more memory
>> than you need early in the program, so you've got a bit already to hand
>> when you run a crucial bit of the program. Or you could tell the user
>> that unfortunately the program can't do what was requested.
>>
>> Getting more memory from the stack seems a little risky, as there are
>> normally less checks whether it worked. Swapping your own program's data
>> out to disk might be a possibility if you keep track of what you have
>> done. Swapping other programs out to disk is system-specific, if you
>> want to try this then other newsgroups will be able to give better help.
> 
> What I mean is, imagine a very large allocation say 4MB. Maybe that's not 
> available in one chunk, however 4 seperate 1MB allocations could succeed. 
> That sort of thing.


Here's code that shows how to do something like that:
#define BLOCK_SIZE 0x40000000
#define NUM_BLOCKS 4
#define BUFFER_SIZE (NUM_BLOCKS * BLOCK_SIZE)

// Note: on many systems the calculation of BUFFERSIZE will overflow

int func(void)
{
    void *blocks[NUM_BLOCKS] = {0};
    int numb;
    blocks[0] = malloc(BUFFER_SIZE);
    // Even if the calculation doesn't overflow, the conversion to
    // size_t may cause unsigned wrap-around. I'll leave it as an
    // exercise for the reader to figure out how to deal with those
    // possibilities.

    if(blocks[0])
    {
        for(numb=0; numb<NUM_BLOCKS-1; numb++)
            blocks[numb+1] = blocks[numb] + BLOCK_SIZE;
    }
    else
    {
        for(numb=0; numb<NUM_BLOCKS && blocks[numb]=malloc(BLOCK_SIZE);
	   numb++);
    }
    if(numb == NUM_BLOCKS)
    {
        // code that works with blocks[];
        // the key thing is that this code doesn't care whether or not
        // the block of memory pointed at by block[1] immediately
        // follows the block pointed at by block[2].
    }
    else
    {
        // error handling for insufficient memory
    }
    while(numb>0)
        free(blocks[--numb]);
}

However, if you can write your code to work with 4 smaller blocks, it's
probably best to always allocate 4 blocks, rather than one large one.

> By stack I mean essentially a local array, i.e.
> func()
> {
>   char buf[1000]; /* <--- example */
>   /* buf can never be Null */
> }
> 
> Note, that in this case, Null can never be returned for the array.

OK, that's a different approach. Here's some code that shows how
something like that could be done:

int called(void*); // This function does the actual work.

int caller(void)
{
    void *p = malloc(BUFFER_SIZE);
    if(p)
         return called(p);
    else
    {
         char buf[BUFFER_SIZE];
         return called(buf);
    }
}

Note: if p is non-null, it's guaranteed to be correctly aligned for any
object type. No such guarantee applies to buf. If called() makes use of
the pointer in any way that requires a special alignment, you need to do
something to make sure that 'buf' is suitably aligned. In C99, you
should declare the parameter of called() as being a pointer to an object
with suitable alignment requirements, and declare buf to be an array of
that same object type. C 2011 adds some new alignment-oriented features
that allow for more exotic ways of achieving that same purpose, but this
is still the most appropriate method to use.

On many systems, the memory pointed at by 'p' comes out of the heap,
while 'buf' resides on the stack, but the C  standard doesn't use those
terms, and does not require that such things even exist. The stack and
the heap could be two separate memory pools, or they could be different
ends of the same block of memory; more complicated alternatives exist as
well. If they are from a single block of memory, not having enough heap
for malloc() to succeed could correspond to not having enough stack for
the allocation of buf to occur. If that's the case, the behavior of that
program is undefined, and there's nothing you can do to prevent that,
anticipate that, or deal with it.

[toc] | [prev] | [next] | [standalone]


#26258

FromJohn Gordon <gordon@panix.com>
Date2012-09-12 20:55 +0000
Message-ID<k2qsrd$9d2$1@reader1.panix.com>
In reply to#26255
In <k2qrlc$ea5$1@speranza.aioe.org> Eric <nospam@nospam.com> writes:

> Sorry maybe I wasn't too clear. I would like to get the Malloc call to 
> succeed if I redo it. Or get some alternative memory eg from the stack or 
> swop.

If malloc is returning null, there isn't a lot you can do.

You can wait a short interval and pray that more memory becomes available
(perhaps some other program just exited, freeing up a lot of memory.)

You can free some memory that your program is using elsewhere.

-- 
John Gordon                   A is for Amy, who fell down the stairs
gordon@panix.com              B is for Basil, assaulted by bears
                                -- Edward Gorey, "The Gashlycrumb Tinies"

[toc] | [prev] | [next] | [standalone]


#26268

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2012-09-12 14:33 -0700
Message-ID<3mb7i9-q9p.ln1@wilbur.25thandClement.com>
In reply to#26258
John Gordon <gordon@panix.com> wrote:
> In <k2qrlc$ea5$1@speranza.aioe.org> Eric <nospam@nospam.com> writes:

> > Sorry maybe I wasn't too clear. I would like to get the Malloc call to
> > succeed if I redo it. Or get some alternative memory eg from the stack
> > or swop.

> If malloc is returning null, there isn't a lot you can do.

> You can wait a short interval and pray that more memory becomes available
> (perhaps some other program just exited, freeing up a lot of memory.)

> You can free some memory that your program is using elsewhere.

Or you could fail that _particular_ operation.

Most software is multifaceted. Excepting a command-line tool or something
performing a discrete operation, there's rarely a persuasive excuse for an
application to abort on allocation failure. Just unwind and fail the
particular context effected by the malloc failure, the same way you'd fail
if a file couldn't be opened or a passwd failed to authenticate.

If you open a web page and it consumes too much memory, don't exit the
browser. If a server-side generated web page consumes too much memory, don't
exit the web server. If an e-mail client uncompressed a trojan attachment
which expands to a terabyte of 0s, don't abort the e-mail client.

[toc] | [prev] | [next] | [standalone]


#26326

Fromfalk@rahul.net (Edward A. Falk)
Date2012-09-13 22:43 +0000
Message-ID<k2tnj8$trh$2@blue-new.rahul.net>
In reply to#26258
In article <k2qsrd$9d2$1@reader1.panix.com>,
John Gordon  <gordon@panix.com> wrote:
>In <k2qrlc$ea5$1@speranza.aioe.org> Eric <nospam@nospam.com> writes:
>
>> Sorry maybe I wasn't too clear. I would like to get the Malloc call to 
>> succeed if I redo it. Or get some alternative memory eg from the stack or 
>> swop.
>
>If malloc is returning null, there isn't a lot you can do.

Pretty much this.

>You can wait a short interval and pray that more memory becomes available
>(perhaps some other program just exited, freeing up a lot of memory.)
>
>You can free some memory that your program is using elsewhere.

This is your best bet.  Does your app have an "undo" buffer?  If so,
flush it.  Is it caching anything?  Flush the caches.  Does the
application allow the user to have multiple files or windows opened?
If so, abort the operation and suggest to the user that they close any
unused windows or files.

If those options aren't available to you, you're pretty much boned.

Or as other posters have suggested, have an alternative algorithm
available that uses less memory, or just fail that particular operation
and hope that the user can live with it.

-- 
	-Ed Falk, falk@despams.r.us.com
	http://thespamdiaries.blogspot.com/

[toc] | [prev] | [next] | [standalone]


#26266

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-09-12 17:37 -0400
Message-ID<50510086.9010908@verizon.net>
In reply to#26255
On 09/12/2012 04:34 PM, Eric wrote:
...
> Sorry maybe I wasn't too clear. I would like to get the Malloc call to 
> succeed if I redo it. Or get some alternative memory eg from the stack or 
> swop.

When it is possible to do something like that (which is seldom the
case), it is essential that you have one or more blocks of memory
somewhere that you can free(), so that you can retry the malloc() with
some chance of having it succeed.
Problem: if you allocated those other blocks of memory, you either need
to write to them, or you need access to information that has already
been written to them. If neither of those are the case, those other
blocks should either a) not have been allocated yet or b) should have
already been free()d.
Therefore, you're going to have to figure out some alternative way of
dealing with whatever it is that you allocated those other memory blocks
for, an alternative that does not require as much memory. That's the
hard part, and is one reason why this approach is seldom used.

An example that could come up in my own code (if it were radically
re-designed). Several of my programs process one scan of data (13,540
pixels) at a time. Those programs could, instead, have been written to
process only one frame of data (10 pixels) at a time. There's some
inefficiency to doing so, so it would run a bit slower, but it would
also require a lot less memory.

[toc] | [prev] | [next] | [standalone]


#26288

FromJohann Klammer <klammerj@NOSPAM.a1.net>
Date2012-09-13 08:57 +0200
Message-ID<505183c6$0$18688$91cee783@newsreader03.highway.telekom.at>
In reply to#26255
Eric wrote:
>
> Sorry maybe I wasn't too clear. I would like to get the Malloc call to
> succeed if I redo it. Or get some alternative memory eg from the stack or
> swop.

Some ideas, most of them difficult to do:
Do it like linux kernel...
If you are using in-memory caches for various things(file i/o, expensive 
calculations), you can try reclaiming those.
If you hack up your own datastructures, you could serialize those to 
disk on-demand.
Both of these would require you to override the allocation functions at 
least. Also, your allocator would have to know of all the reclaimable 
areas. Possibly prioritize things... File caching may fail, other things 
must succeed.
Never tried any of this myself, but it is surely possible...

[toc] | [prev] | [next] | [standalone]


#26262

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-09-12 17:20 -0400
Message-ID<5050FC9D.4010608@verizon.net>
In reply to#26252
On 09/12/2012 04:07 PM, Eric wrote:
> Hi What is a good way to respond to a failed Malloc (returns Null)? I do 
> not want to call Abort or Exit immediately.

That depends entirely upon what your program is doing. There's only one
general piece of advice that's applicable: do NOT do anything with that
null pointer value other than copying it or comparing it to other pointers.

My own code would generate an error message identifying the fact that
malloc() failed, along with the name of the function that called it, and
the name of the file containing that function. That much is required by
the coding standards for the project I'm working on. Everything else I
will say about this reflects my own personal requirements. If the
failure occurred inside a loop, the error message would indicate the
value of the loop index at the time the problem was identified. If the
message would otherwise be identical to another message that could be
produced in the same block of code, something will be added to it to
allow unique identification of the particular call to malloc() that
triggered the problem. That function would then clean up anything that
it needed to clean up, and then return an error code to the calling
function.

The calling function would respond to that error code by generating
another error message containing the same type of information for the
calling function as was described above for the function in which the
problem was originally detected. This continues all the way up the call
chain to main(), which would generate a final error message before
returning EXIT_FAILURE. The net effect is an annotated reverse
stack-trace. That information isn't particularly useful when dealing
with malloc() failures, but it's part of a general architecture for
dealing with error conditions that helps me get a running start on
diagnosing the underlying problem.

This is a totally inappropriate way of handling error conditions for
many contexts, such as interactive GUI programs. However, most of my
code exclusively runs inside a batch processing environment, where this
is quite a reasonable approach.

You need to figure out the right approach for your purposes.

[toc] | [prev] | [next] | [standalone]


#26263

FromIan Collins <ian-news@hotmail.com>
Date2012-09-13 09:27 +1200
Message-ID<abcd17F1taiU1@mid.individual.net>
In reply to#26262
On 09/13/12 09:20 AM, James Kuyper wrote:
> On 09/12/2012 04:07 PM, Eric wrote:
>> Hi What is a good way to respond to a failed Malloc (returns Null)? I do
>> not want to call Abort or Exit immediately.
>
> That depends entirely upon what your program is doing. There's only one
> general piece of advice that's applicable: do NOT do anything with that
> null pointer value other than copying it or comparing it to other pointers.
>
> My own code would generate an error message identifying the fact that
> malloc() failed, along with the name of the function that called it, and
> the name of the file containing that function. That much is required by
> the coding standards for the project I'm working on. Everything else I
> will say about this reflects my own personal requirements. If the
> failure occurred inside a loop, the error message would indicate the
> value of the loop index at the time the problem was identified. If the
> message would otherwise be identical to another message that could be
> produced in the same block of code, something will be added to it to
> allow unique identification of the particular call to malloc() that
> triggered the problem. That function would then clean up anything that
> it needed to clean up, and then return an error code to the calling
> function.

I can understand this approach on a single use embedded system where 
such a failure may be repeatable. Do error messages provide any useful 
data on a multi-user system given the generally random memory usage 
patterns?

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#26269

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-09-12 17:56 -0400
Message-ID<505104F1.6080709@verizon.net>
In reply to#26263
On 09/12/2012 05:27 PM, Ian Collins wrote:
> On 09/13/12 09:20 AM, James Kuyper wrote:
>> On 09/12/2012 04:07 PM, Eric wrote:
>>> Hi What is a good way to respond to a failed Malloc (returns Null)? I do
>>> not want to call Abort or Exit immediately.
>>
>> That depends entirely upon what your program is doing. There's only one
>> general piece of advice that's applicable: do NOT do anything with that
>> null pointer value other than copying it or comparing it to other pointers.
>>
>> My own code would generate an error message identifying the fact that
>> malloc() failed, along with the name of the function that called it, and
>> the name of the file containing that function. That much is required by
>> the coding standards for the project I'm working on. Everything else I
>> will say about this reflects my own personal requirements. If the
>> failure occurred inside a loop, the error message would indicate the
>> value of the loop index at the time the problem was identified. If the
>> message would otherwise be identical to another message that could be
>> produced in the same block of code, something will be added to it to
>> allow unique identification of the particular call to malloc() that
>> triggered the problem. That function would then clean up anything that
>> it needed to clean up, and then return an error code to the calling
>> function.
> 
> I can understand this approach on a single use embedded system where 
> such a failure may be repeatable. Do error messages provide any useful 
> data on a multi-user system given the generally random memory usage 
> patterns?

While the systems my programs normally run on are nominally multi-user,
there's one user-id that is used to start the production manager
program. All other programs in the production system (including mine)
are started by the manager, directly or indirectly, and therefore all
run using the same user id. For practical purposes, it's a single-user
system (and definitely NOT an embedded one).

As I said, for failed malloc() calls the information provided by those
error messages is seldom of much use - it's just part of a general
framework for error handling that I've found useful. However, most of
the problems that come up are data-driven, and are unaffected by the
"random memory use patterns" of other programs that might be running at
the same time on the same system. For those kinds of problems, I've
found it a very useful framework.

This is example of how the right way to deal with errors depends very
much on the context in which those errors have to be dealt with, which
is precisely the point I was making.

I was recently assigned to help another group with their work - when it
fails, their software provides much less information in the error
messages than mine does. I keenly miss that information.

[toc] | [prev] | [next] | [standalone]


#26274

FromIan Collins <ian-news@hotmail.com>
Date2012-09-13 10:28 +1200
Message-ID<abcgjrF1taiU4@mid.individual.net>
In reply to#26269
On 09/13/12 09:56 AM, James Kuyper wrote:
> On 09/12/2012 05:27 PM, Ian Collins wrote:
>> On 09/13/12 09:20 AM, James Kuyper wrote:
>>> On 09/12/2012 04:07 PM, Eric wrote:
>>>> Hi What is a good way to respond to a failed Malloc (returns Null)? I do
>>>> not want to call Abort or Exit immediately.
>>>
>>> That depends entirely upon what your program is doing. There's only one
>>> general piece of advice that's applicable: do NOT do anything with that
>>> null pointer value other than copying it or comparing it to other pointers.
>>>
>>> My own code would generate an error message identifying the fact that
>>> malloc() failed, along with the name of the function that called it, and
>>> the name of the file containing that function. That much is required by
>>> the coding standards for the project I'm working on. Everything else I
>>> will say about this reflects my own personal requirements. If the
>>> failure occurred inside a loop, the error message would indicate the
>>> value of the loop index at the time the problem was identified. If the
>>> message would otherwise be identical to another message that could be
>>> produced in the same block of code, something will be added to it to
>>> allow unique identification of the particular call to malloc() that
>>> triggered the problem. That function would then clean up anything that
>>> it needed to clean up, and then return an error code to the calling
>>> function.
>>
>> I can understand this approach on a single use embedded system where
>> such a failure may be repeatable. Do error messages provide any useful
>> data on a multi-user system given the generally random memory usage
>> patterns?
>
> While the systems my programs normally run on are nominally multi-user,
> there's one user-id that is used to start the production manager
> program. All other programs in the production system (including mine)
> are started by the manager, directly or indirectly, and therefore all
> run using the same user id. For practical purposes, it's a single-user
> system (and definitely NOT an embedded one).
>
> As I said, for failed malloc() calls the information provided by those
> error messages is seldom of much use - it's just part of a general
> framework for error handling that I've found useful. However, most of
> the problems that come up are data-driven, and are unaffected by the
> "random memory use patterns" of other programs that might be running at
> the same time on the same system. For those kinds of problems, I've
> found it a very useful framework.
>
> This is example of how the right way to deal with errors depends very
> much on the context in which those errors have to be dealt with, which
> is precisely the point I was making.
>
> I was recently assigned to help another group with their work - when it
> fails, their software provides much less information in the error
> messages than mine does. I keenly miss that information.

I understand your pain.  I use a similar approach to resource allocation 
failures to yours in C++ with exceptions that convey file and line 
number information from the call site.  These can ether propagate up or 
be caught and augmented and re-thrown higher up the stack.  I guess I 
haven't done anything similar in C because it takes more work and lot 
more discipline!

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#26277

FromJames Kuyper <jameskuyper@verizon.net>
Date2012-09-12 18:57 -0400
Message-ID<50511364.5030408@verizon.net>
In reply to#26274
On 09/12/2012 06:28 PM, Ian Collins wrote:
...
> I understand your pain.  I use a similar approach to resource allocation 
> failures to yours in C++ with exceptions that convey file and line 
> number information from the call site.  These can ether propagate up or 
> be caught and augmented and re-thrown higher up the stack.  I guess I 
> haven't done anything similar in C because it takes more work and lot 
> more discipline!

On my new task, I'm actually using C++, and I've been trying to figure
out how to make use of exceptions to produce the same kind of error
output I get from the my C programs. It's a fantasy, since the new group
I'm working with has it's own well-entrenched error handling conventions
that would not mix well with my preferred style.

However, when I did indulge that fantasy, I found that one key problem
was that exceptions discard information about where they came from, as
the call stack unwinds. Unless I catch and rethrow around every function
call that could throw an exception (including the implicit function
calls due to ctors, dtors, and operator overloads), it can't duplicate
the information generated by my error messages.

If I did catch and rethrow everywhere, it would end up looking very
similar to my current C code, which constantly checks for error codes.
More than one person has looked at my code and come away with the
impression that its primary purpose was error handling. One person even
submitted a test plan for a module that triggered every single error
message that could be generated by that module, but failed to cover
normal processing.

I'd hoped to find a way to use C++ exceptions to reduce the error
message clutter, but I can't figure out how to do so without a
corresponding reduction in the amount of information conveyed by the
error messages.

[toc] | [prev] | [next] | [standalone]


#26280

FromWilliam Ahern <william@wilbur.25thandClement.com>
Date2012-09-12 16:21 -0700
Message-ID<m0i7i9-noi.ln1@wilbur.25thandClement.com>
In reply to#26277
James Kuyper <jameskuyper@verizon.net> wrote:
> On 09/12/2012 06:28 PM, Ian Collins wrote:
> ...
> > I understand your pain.  I use a similar approach to resource allocation 
> > failures to yours in C++ with exceptions that convey file and line 
> > number information from the call site.  These can ether propagate up or 
> > be caught and augmented and re-thrown higher up the stack.  I guess I 
> > haven't done anything similar in C because it takes more work and lot 
> > more discipline!

> On my new task, I'm actually using C++, and I've been trying to figure
> out how to make use of exceptions to produce the same kind of error
> output I get from the my C programs. It's a fantasy, since the new group
> I'm working with has it's own well-entrenched error handling conventions
> that would not mix well with my preferred style.

> However, when I did indulge that fantasy, I found that one key problem
> was that exceptions discard information about where they came from, as
> the call stack unwinds. Unless I catch and rethrow around every function
> call that could throw an exception (including the implicit function
> calls due to ctors, dtors, and operator overloads), it can't duplicate
> the information generated by my error messages.

You could use libbfd (used by GDB) to lookup symbols. And putting together** a
stack trace is pretty easy, especially given that you're not generating one
from a signal handler--crossing the signal trampoline is a PITA.

Not ideal, of course. For many reasons. But it can definitely cut down on
the code clutter.


** There are libraries to do this, but they either try to do too much, or do
too little. And in any event, the hard part is grokking the symbols, thus
libbfd. I wrote mine in ~1000 SLoC, but the majority of that is signal-safe
implementations of date-time routines (e.g. gmtime) and formatted I/O, as I
also had to trace and log from within a signal handler.

[toc] | [prev] | [next] | [standalone]


Page 1 of 2  [1] 2  Next page →

Back to top | Article view | comp.lang.c


csiph-web