Re: xmalloc string functions
- From: ymuntyan@xxxxxxxxx
- Date: Tue, 29 Jan 2008 01:23:21 -0800 (PST)
On Jan 29, 2:56 am, Nick Keighley <nick_keighley_nos...@xxxxxxxxxxx>
wrote:
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?
Yes. It got to put the data somewhere.
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
You mean nice versus one is very few? OK.
And how
many lines of code will you get if you do it ten times?
still very few
OK.
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?
And a code parser which will find all malloc() calls,
and then a script generator which will generate all
possible code paths to make debugger test those
places. I'd be glad to have such a tool, certainly.
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().
Except where you got a bug. In the place you won't
test.
(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.
So do it. You *can*. Glib doesn't do anything but abort()
by default, naturally, since it can't do anything else.
If you are fine with this, do nothing. If not, write code
which will save the user data.
And man, I didn't say we should lose the user data!
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.
So do it? Who said you shouldn't it? You can save data
and terminate. But you ought to terminate, with saving
or not, if you use glib. That's it. But I am told that
an application can do more. No it can't. If the main loop
can't push an event onto the event queue, then you're
screwed. No "application performs worse" or "some parts
are not working". (Note, it is not about all applications,
don't talk about failsafe mp3 players or about webservers,
those simply shouldn't use glib)
Yevgen
.
- Follow-Ups:
- Re: xmalloc string functions
- From: Nick Keighley
- Re: xmalloc string functions
- References:
- xmalloc string functions
- From: Malcolm McLean
- Re: xmalloc string functions
- From: Yevgen Muntyan
- Re: xmalloc string functions
- From: William Ahern
- Re: xmalloc string functions
- From: Yevgen Muntyan
- Re: xmalloc string functions
- From: William Ahern
- Re: xmalloc string functions
- From: Yevgen Muntyan
- Re: xmalloc string functions
- From: William Ahern
- Re: xmalloc string functions
- From: Yevgen Muntyan
- Re: xmalloc string functions
- From: William Ahern
- Re: xmalloc string functions
- From: Yevgen Muntyan
- Re: xmalloc string functions
- From: Flash Gordon
- Re: xmalloc string functions
- From: ymuntyan
- Re: xmalloc string functions
- From: Kelsey Bjarnason
- Re: xmalloc string functions
- From: ymuntyan
- Re: xmalloc string functions
- From: Nick Keighley
- xmalloc string functions
- Prev by Date: Re: Copy memory (array)
- Next by Date: Re: When to check the return value of malloc
- Previous by thread: Re: xmalloc string functions
- Next by thread: Re: xmalloc string functions
- Index(es):
Relevant Pages
|