Re: xmalloc string functions



On 29 Jan, 08:25, ymunt...@xxxxxxxxx wrote:
On Jan 28, 11:40 am, Kelsey Bjarnason <kbjarna...@xxxxxxxxx> wrote:
On Mon, 28 Jan 2008 15:30:50 -0800, ymuntyan wrote:

No idea, ask the developers of that buggy application. Failed fopen()
is not an exceptional condition. Failed malloc() is. Or we are using
different vocabularies.

The point is that they both require similar recovery strategies.

The point is that they don't. If fopen() fails, there is nothing to
recover from.

If my fopen fails and I can't load my app's config file, I can't get the
preferred options.  Depending on the app, this could be anything from a
minor annoyance to a critical failure.  In every one of those cases,
there is something to recover from.

If my fopen fails because the user has no read permissions (or no write
permissions, if he's trying to open for write), there is something to
recover from - let him know he has no permissions, go back to the file
select dialog (or whatever called fopen) and let the user decide what to
do about it - choose a different file name, fix the permissions, whatever.

I'm sorry, but "there's nothing to recover from" is just so completely
out of touch with reality I can't believe you said it.

So, you work with a list, and you append an element to it. Now you do
list = g_list_append(list, something); with malloc error handling you'll
have to test whether list_append() succeeded.

does g_list_append() allocate memory?


That depends entirely on how your list functions work.  As a simple
example:

/* NODE and LIST are actually the same thing, just written differently
for clarity's sake */
void list_append( LIST *list, NODE *new )
{
  NODE *node = list;

  /* Find end of list */
  while( node->next != NULL )
   node = node->next;

  /* Add item to end of list */
  node->next = new;
  new->next = NULL;

}

Sorry, what, exactly, did I need to check here with malloc error
handling?  What's that you say, nothing at all, since there _is_ no
malloc involved in adding a node to the list?  Ah, yes.  Of course, we
need to allocate the node itself:

NODE *node;
LIST *list;

...

node = malloc( sizeof( *node ) );
if ( node == NULL )
{
 blah}

else
{
  list_append( list, node );
  blah

}

Golly, how unbearably painful.

Oh yes. Easy. How many lines of code is that?

very few

And how
many lines of code will you get if you do it ten times?

still very few

That is, lines of untested code (no, I won't buy the
tales that you will test it. You won't)

it seems you're assumptions about his development methodology


I can test it relatively easily. For example, I can use a malloc
wrapper which allows me to force a return of a null pointer when I want
during testing. Or I can use the debugger to put a breakpoint in and
change the pointer value to null at the point I want to trigger the
failure.

There are about five bazillion allocations, debugger won't do.

and the wrapper?

Random
malloc() failures will do as a nice stress test, yes. But you still
won't be able to test it properly. At least not that piece of code where
it will segfault when user runs it

Huh?  A segfault is a result, generally, of one of two things: a runaway
pointer, or an allocation failure - you know, the very thing we're
suggesting you actually design your code to test for.

I'm saying that you got so many possible segfault places
that you won't test the one where it will actually segfault.

there won't be *any* segfault places. You ALWAYS test the return from
malloc().


(here I assume that user will be able
to see it, perhaps on windows). A better thing to do is to test malloc()
failure in one place, and possibly do what you can do there, and abort..

Really?  Okay, fine.  I've got allocated data buffers *with live data* in
793 different places in the code.  The only way your "one place" is going
to be able to "do what you can there" and save the data is if every
single piece of data in the entire program is a freaking *global*, which
is *not* gonna happen.

Now, if I don't use this half-baked notion of "allocate or die", I can
report the failure to the caller, and then to its caller, and so on and
so forth, with each level doing whatever is appropriate for the data it
has in its care, *none* of which your method has *any* ability to do.

But hey, it's not like data matters, right?  Who cares, data's worthless,
just crash the app.

Okay, okay. After we crashed the application and lost user data,

no no no! The point is you do something with the user data
*before* you terminate the application.

let's talk about that old boring main loop. Who is it going to
report errors to?

I'm not sure what your loop does.


After we failed to process an event in the user
code, user code returns an error to the events dispatcher. What
does that do?

if the user code saves the data the event loop can terminate.
Your crashing malloc() doesn't allow this option.
You make the decisions in the user code which understands the
application and not in the malloc library.


Pretends nothing happened? What do you do if signal
emission failed because you can't allocate memory required for
the emission? The callbacks must be called, otherwise you get
all sorts of funny results, including data loss. You just got
to quit the application, that's all you can do. Save the data
if you can, certainly.

but you can't do that in your code!


Yes, *real*. No, g_malloc() aborting an application is not a real
problem. Not for a regular desktop application.

You have just had pointed out to you a time when it has been a problem
for a user.

Yeah, mozilla leaking too much. Or evolution leaking too much (?).

Could be either.  Point is, we know that _real world_ applications _are_
dying from this design principle, which means that while today it's "only
a browser", there's no telling what it will be tomorrow.

Err, if an application eats too much memory then the die-on-oom
simply doesn't work for it. It's the application bug if it eats
too much memory and dies. When gedit crashes because of malloc()
failure, *then* there will be a gedit bug. Hypothetical abort()
in gedit is not something I would worry about if I were a gedit
developer.

why not?


I've previously pointed out times when applications have given me a
chance to recover the situation and it has avoided me loosing a lot of
work.

Avoiding losing your work in an emergency condition is just a different
story

No, it's the same story.  Application tried to allocate something,
couldn't, *died* and took the data with it.  Depending on the app - and
the data - this would be grounds for anything from simply pulling hair
out to actually hunting down the developer with a baseball bat.  Or a
lawyer.

So don't lose data? You can avoid losing data with glib, yes.
Just please stop talking this stuff about losing data. Data
must not be lost, period. An application may abort on malloc()
failure, period. These two *are* possible to combine.

how? This makes no sense.


Not necessarily. For example, if you have done your job correctly the
*recovery* code already has the memory it needs allocated, so that can
run successfully.

Recovery code will be able to run successfully, so what?

"So what" is that my data wasn't hooped by your brain-dead strategy of
simply aborting on error, that's what.  I know you don't think users'
data actually *means* anything, but I can assure you, the *user* thinks
it does.

Sorry, I didn't say lose data. I said you can't continue working
as nothing happened after that. "Recovery code will be able to run
successfully", right. Now read what you snipped, and *then* argue

"recovery" includes saving data and terminating.


--
Nick Keighley
.



Relevant Pages

  • Re: xmalloc string functions
    ... If these were the only choices (crashing applications or a frozen ... trying to malloc some rediculously large amount of memory - e.g. in the ... because their malloc wrapper decided to exit. ... Exiting on malloc failure makes sense for a utility like sort. ...
    (comp.lang.c)
  • Re: xmalloc string functions
    ... Failed malloc() is. ... minor annoyance to a critical failure. ... there is something to recover from. ... Now, if I don't use this half-baked notion of "allocate or die", I can ...
    (comp.lang.c)
  • Re: xmalloc string functions
    ... than a NULL return from malloc(). ... pointer value to null at the point I want to trigger the failure. ... I've also had VMWare report out-of-resource at times when the only resource that was tight was memory, and again it gave me the chance to recover the situation which saved me significant work because I had two VMs running and the state between them was important and took time setting up. ... allocations without reference to other circumstances (number of ...
    (comp.lang.c)
  • Re: xmalloc string functions
    ... malloc() failures will do as a nice stress test, ... pointer, or an allocation failure - you know, the very thing we're ... Why not follow a policy of try and allocate ... memory, if it fails take some application specific recovery action? ...
    (comp.lang.c)
  • Re: xmalloc string functions
    ... than a NULL return from malloc(). ... pointer value to null at the point I want to trigger the failure. ... There are about five bazillion allocations, ... Memory is quite a different kind of resource. ...
    (comp.lang.c)