473,320 Members | 1,802 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

xmalloc

Continuing the error-handling thread.

I am floating

void *xmalloc(int sz)
{
void *answer;

assert(sz >= 0);
if(sz == 0)
sz = 1;
answer = malloc(sz);
if(!answer)
{
fprintf(stderr, "Can't allocate %d byte%c\n", sz, sz == 1 ? ' ', 's');
exit(EXIT_FAILURE);
}
return answer;
}

as a solution to the malloc() problem.
(Chuck Falconer's suggestion)
You call it for trivial allocations on the basis that if the computer won't
give a few bytes of memory, not much can be done.
However you wouldn't call it to allocate an image, for example, because
legitmate images can be quite large in relation to computer memories.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 23 '07 #1
51 5409
Malcolm McLean said:
Continuing the error-handling thread.

I am floating

void *xmalloc(int sz)
{
void *answer;

assert(sz >= 0);
if(sz == 0)
sz = 1;
answer = malloc(sz);
if(!answer)
{
fprintf(stderr, "Can't allocate %d byte%c\n", sz, sz == 1 ? ' ',
's'); exit(EXIT_FAILURE);
}
return answer;
}

as a solution to the malloc() problem.
What malloc() problem? And this "solution" suffers from the same problem
as any other "solution" of the same kind - it's no earthly use in a
library, and libraries are where malloc calls belong.

There are two reasons why it's no earthly use in a library.

For one thing, it displays a message on stderr, which isn't much cop in
a system where stderr messages are ignored - e.g. a Win32 GUI app. But
that's trivial to fix - either remove the message completely, or add a
callback or a pointer to an error code, so that the application can
worry about how to display the message.

The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.

Here's my suggested replacement, which incorporates all the fixes I see
as being necessary:

#include <stdlib.h>

void *xmalloc(size_t sz)
{
return malloc(sz);
}

You call it for trivial allocations on the basis that if the computer
won't give a few bytes of memory, not much can be done.
Whether that is true depends on the problem you're trying to solve. For
example, it may well be possible to switch to a static solution which
is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 23 '07 #2

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:kb******************************@bt.com...
Malcolm McLean said:
>Continuing the error-handling thread.

I am floating

void *xmalloc(int sz)
{
void *answer;

assert(sz >= 0);
if(sz == 0)
sz = 1;
answer = malloc(sz);
if(!answer)
{
fprintf(stderr, "Can't allocate %d byte%c\n", sz, sz == 1 ? ' ',
's'); exit(EXIT_FAILURE);
}
return answer;
}

as a solution to the malloc() problem.

What malloc() problem? And this "solution" suffers from the same problem
as any other "solution" of the same kind - it's no earthly use in a
library, and libraries are where malloc calls belong.

There are two reasons why it's no earthly use in a library.

For one thing, it displays a message on stderr, which isn't much cop in
a system where stderr messages are ignored - e.g. a Win32 GUI app. But
that's trivial to fix - either remove the message completely, or add a
callback or a pointer to an error code, so that the application can
worry about how to display the message.

The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.

Here's my suggested replacement, which incorporates all the fixes I see
as being necessary:

#include <stdlib.h>

void *xmalloc(size_t sz)
{
return malloc(sz);
}

>You call it for trivial allocations on the basis that if the computer
won't give a few bytes of memory, not much can be done.

Whether that is true depends on the problem you're trying to solve. For
example, it may well be possible to switch to a static solution which
is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.
In which case would call regular malloc()
However you are doubling the cost of the software with that strategy, all
because a 2GB machine might refuse to give a few hundred bytes of memory. If
it is running a life-support machine, fair enough, but most software
doesn't.

On the other hand you could argue that xmalloc() is a bad idea, because no
library that uses it could ever find its way into a life-support machine.
On the other hand, you could argue that the life support machine is more
likely to blow a fuse than to exit in xmalloc(), so you need a backup
anyway.

I take your point about vandalised stderrs.
Maybe we should put an assert fail in there as well / instead.
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jun 23 '07 #3
Malcolm McLean said:
>
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:kb******************************@bt.com...
>Malcolm McLean said:
<snip>
>>You call it for trivial allocations on the basis that if the
computer won't give a few bytes of memory, not much can be done.

Whether that is true depends on the problem you're trying to solve.
For example, it may well be possible to switch to a static solution
which is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.
In which case would call regular malloc()
However you are doubling the cost of the software with that strategy,
all because a 2GB machine might refuse to give a few hundred bytes of
memory.
The way I see it is this: by writing an inferior program that is
prepared to bomb out at the drop of a hat, I can *reduce* the cost of
writing the program, but it *would be* an inferior program. And then
I'd have to market the program to the kind of people who used to buy
Cortinas, or Edsels. I prefer to deal with Maserati types. :-)

<snip>

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 23 '07 #4
On Sat, 23 Jun 2007 18:47:44 +0000, Richard Heathfield wrote:
>The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.
You can often see programs that check the return value of malloc but
you hardly (practically never) see any code that actually handles the
OOM (out-of-memory) condition (e.g. frees some pre-allocated memory).
Strange, isn't it?
Moreover, C libraries usually crash when the caller provides
insufficient resources or invalid arguments. In that sense abort() is
preferable to exit() for OOM.
>For
example, it may well be possible to switch to a static solution which
is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.
The 'static solution' may cause a 'stack' overflow. BTW, how would you
handle the second type of OOM, 'stack' overflow? The same way as OOM
for dynamic memory?
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 23 '07 #5
Malcolm McLean wrote:
[...]
However you are doubling the cost of the software with that strategy,
all because a 2GB machine might refuse to give a few hundred bytes of
memory. [...]
A 2GB machine *will* refuse to allocate a few hundred
bytes of memory -- immediately after a successful allocation
of 2GB. Maybe the program could choose to discard the 2GB
allocation that's just holding a bunch of cache, and try again
on the couple hundred bytes it Really Needs? Too late, Malcolm
has already euthanized it. Requesciat in pacem.

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 23 '07 #6
Roland Pibinger said:

<snip>
You can often see programs that check the return value of malloc but
you hardly (practically never) see any code that actually handles the
OOM (out-of-memory) condition (e.g. frees some pre-allocated memory).
Strange, isn't it?
Yes. It's a great shame.
Moreover, C libraries usually crash when the caller provides
insufficient resources or invalid arguments. In that sense abort() is
preferable to exit() for OOM.
Well, I do see your point, but personally I'd prefer for the program to
make sensible choices that minimise inconvenience to the user.
>>For
example, it may well be possible to switch to a static solution which
is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.

The 'static solution' may cause a 'stack' overflow.
So make sure it doesn't, by avoiding stress to your 'stack'.
BTW, how would you
handle the second type of OOM, 'stack' overflow? The same way as OOM
for dynamic memory?
One of the reasons dynamic memory is so useful is that there's a heck of
a lot of it to go around, compared to a typical 'stack' - but the other
great advantage thereof is that you /can/ detect an OOM condition with
malloc, whereas you can't with 'stack' overflow - at least, not
portably. Nevertheless, you can still do quite a lot with a 'stack'
that doesn't involve a significant risk of overflow (the adjective
being necessary only because the C Standard gives us very little in the
way of guarantees about 'stack' capacity - in practice, nowadays it is
only a problem if you treat the 'stack' rather recklessly).

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 23 '07 #7
Roland Pibinger wrote:
On Sat, 23 Jun 2007 18:47:44 +0000, Richard Heathfield wrote:
>The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.

You can often see programs that check the return value of malloc but
you hardly (practically never) see any code that actually handles the
OOM (out-of-memory) condition (e.g. frees some pre-allocated memory).
Strange, isn't it?
Not all that strange. Half the programmers in the world
are below-average.

But if you follow Malcolm's Maxims, even the above-average
programmers will be helpless. Programs that deal with malloc()
failure in a significant way may be a minority, but those that
do it *need* to to do it. Malcolm argues, in essence, that
such programs should not be written in C.
Moreover, C libraries usually crash when the caller provides
insufficient resources or invalid arguments. In that sense abort() is
preferable to exit() for OOM.
Oh, heaven spare us! Not only do you want to kill off
the program, but you also want to prevent it from running
its carefully-registered atexit() handlers? And you don't
care whether buffers are flushed, streams are closed, and
temporary files are removed? What do you do for amusement,
juggle flasks of nitroglycerin while fire-walking?

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 23 '07 #8

"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:46**************@news.utanet.at...
On Sat, 23 Jun 2007 18:47:44 +0000, Richard Heathfield wrote:
>>The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.

You can often see programs that check the return value of malloc but
you hardly (practically never) see any code that actually handles the
OOM (out-of-memory) condition (e.g. frees some pre-allocated memory).
Strange, isn't it?
Moreover, C libraries usually crash when the caller provides
insufficient resources or invalid arguments. In that sense abort() is
preferable to exit() for OOM.
Normally if you've written the program in such a way that it makes a lot of
trival allocations, there is nothing you can do on failure, short of calling
a back-up routine that uses fixed buffers.
So you handle fail conditions for the few large legitimate allocations,
which might run the computer out of memory, and abort on the rest.

You can declare a global "world" pointer, and then in atexit try to save the
state of the program, but there are two problems. Firstly if the OS won't
give you a few hundred bytes, it might well not open files for you either.
Secondly, all the code has to be very carefully written so that an
allocation failure never causes the state to lose coherence. Otherwise you
will crash when you try to write a null pointer, or worse, write an image
that looks right but is in fact subtly corrupted.

So there really isn't an easy answer.
>>For
example, it may well be possible to switch to a static solution which
is perhaps not as fast as the dynamic solution but which will
nevertheless do the Right Thing in a reasonable time.

The 'static solution' may cause a 'stack' overflow. BTW, how would you
handle the second type of OOM, 'stack' overflow? The same way as
OOM for dynamic memory?
So if you use recursive subroutines you've already got one potential source
of crashes on malicious or excessive input. That reduces the motivation to
fix malloc(), because you can't guarantee correct operation anyway.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 23 '07 #9
Richard Heathfield wrote:
Malcolm McLean said:
>Continuing the error-handling thread.

I am floating

void *xmalloc(int sz)
{
Should be size_t.
> void *answer;

assert(sz >= 0);
if(sz == 0)
sz = 1;
answer = malloc(sz);
if(!answer)
{
fprintf(stderr, "Can't allocate %d byte%c\n", sz, sz == 1 ? ' ',
's'); exit(EXIT_FAILURE);
}
return answer;
}

as a solution to the malloc() problem.

What malloc() problem? And this "solution" suffers from the same problem
as any other "solution" of the same kind - it's no earthly use in a
library, and libraries are where malloc calls belong.
It could be enhanced by providing a (cough) global failure function, say
xmalloc_failure, that gets called when malloc returns NULL:

void* default_xmalloc_failure(size_t s) {
assert(!"Can't allocate memory"); return NULL;}

void* (*xmalloc_failure)(size_t) = &default_xmalloc_failure;

The xmalloc becomes

void *xmalloc(size_t sz)
{
void *answer = malloc( sz == 0 ? 1 : sz );
if(answer == NULL)
{
xmalloc_failure(sz);
}
return answer;
}

Which gives the user control over what happens when malloc fails.

--
Ian Collins.
Jun 23 '07 #10
Ian Collins said:

<snip>
It could be enhanced by providing a (cough) global failure function,
say xmalloc_failure, that gets called when malloc returns NULL:

void* default_xmalloc_failure(size_t s) {
assert(!"Can't allocate memory"); return NULL;}

void* (*xmalloc_failure)(size_t) = &default_xmalloc_failure;

The xmalloc becomes

void *xmalloc(size_t sz)
{
void *answer = malloc( sz == 0 ? 1 : sz );
if(answer == NULL)
{
xmalloc_failure(sz);
}
return answer;
}

Which gives the user control over what happens when malloc fails.
It's an improvement, but it's still not good enough as a general
solution. Consider this code:

foo *foo_create(size_t n)
{
static const foo fblank;
foo *new = malloc(sizeof *new); /* A */
if(new != NULL)
{
*new = fblank;
new->bar = malloc(n * sizeof *new->bar); /* B */
if(new->bar == NULL)
{
free(new);
new = NULL;
}
else
{
static const t_bar bblank;
while(n--)
{
new->bar[n] = bblank;
}
}
}
return new;
}

If we were to rewrite this to use your suggestion, that would be fine
for the malloc at A, but if the malloc at B fails, we have to clean up,
and that means that the cleanup code needs access to new. Your solution
doesn't address that problem.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 23 '07 #11

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
news:4d******************************@bt.com...
Ian Collins said:

<snip>
>It could be enhanced by providing a (cough) global failure function,
say xmalloc_failure, that gets called when malloc returns NULL:

void* default_xmalloc_failure(size_t s) {
assert(!"Can't allocate memory"); return NULL;}

void* (*xmalloc_failure)(size_t) = &default_xmalloc_failure;

The xmalloc becomes

void *xmalloc(size_t sz)
{
void *answer = malloc( sz == 0 ? 1 : sz );
if(answer == NULL)
{
xmalloc_failure(sz);
}
return answer;
}

Which gives the user control over what happens when malloc fails.

It's an improvement, but it's still not good enough as a general
solution. Consider this code:

foo *foo_create(size_t n)
{
static const foo fblank;
foo *new = malloc(sizeof *new); /* A */
if(new != NULL)
{
*new = fblank;
new->bar = malloc(n * sizeof *new->bar); /* B */
if(new->bar == NULL)
{
free(new);
new = NULL;
}
else
{
static const t_bar bblank;
while(n--)
{
new->bar[n] = bblank;
}
}
}
return new;
}

If we were to rewrite this to use your suggestion, that would be fine
for the malloc at A, but if the malloc at B fails, we have to clean up,
and that means that the cleanup code needs access to new. Your solution
doesn't address that problem.
How about this

void *xmalloc(size_t sz)
{
void *answer;

if(sz == 0)
sz = 1;
while( !(answer = malloc(sz))
(*malloc_failure(sz));

return answer;
}
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 23 '07 #12
Richard Heathfield wrote:
Ian Collins said:

<snip>
>It could be enhanced by providing a (cough) global failure function,
say xmalloc_failure, that gets called when malloc returns NULL:

void* default_xmalloc_failure(size_t s) {
assert(!"Can't allocate memory"); return NULL;}

void* (*xmalloc_failure)(size_t) = &default_xmalloc_failure;

The xmalloc becomes

void *xmalloc(size_t sz)
{
void *answer = malloc( sz == 0 ? 1 : sz );
if(answer == NULL)
{
xmalloc_failure(sz);
}
return answer;
}

Which gives the user control over what happens when malloc fails.

It's an improvement, but it's still not good enough as a general
solution. Consider this code:

foo *foo_create(size_t n)
{
static const foo fblank;
foo *new = malloc(sizeof *new); /* A */
if(new != NULL)
{
*new = fblank;
new->bar = malloc(n * sizeof *new->bar); /* B */
if(new->bar == NULL)
{
free(new);
new = NULL;
}
else
{
static const t_bar bblank;
while(n--)
{
new->bar[n] = bblank;
}
}
}
return new;
}

If we were to rewrite this to use your suggestion, that would be fine
for the malloc at A, but if the malloc at B fails, we have to clean up,
and that means that the cleanup code needs access to new. Your solution
doesn't address that problem.
Then you have to turn up the complexity another notch an introduce a
cleanup handler stack, which just about takes us back to checking each
return of malloc()!

This situation is one of the reasons I like that unmentionable in these
parts cousin of C with its exceptions and destructors!

--
Ian Collins.
Jun 24 '07 #13
On Sat, 23 Jun 2007 16:30:12 -0400, Eric Sosman wrote:
Not all that strange. Half the programmers in the world
are below-average.
which is at least half-true.
But if you follow Malcolm's Maxims, even the above-average
programmers will be helpless. Programs that deal with malloc()
failure in a significant way may be a minority, but those that
do it *need* to to do it. Malcolm argues, in essence, that
such programs should not be written in C.
The discussion basically boils down to one question: Is OOM an error
that reasonably can and should be handled by the application or is it
a fatal error?
The 'fatal error' advocates have already shown how they tackle the
problem. Now it's time for the other camp to demonstrate how OOM can
be consistently _handled_ throughout the program ('return NULL;' is
not enough).
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 24 '07 #14
On Sat, 23 Jun 2007 22:16:11 +0100, "Malcolm McLean" wrote:
>Normally if you've written the program in such a way that it makes a lot of
trival allocations, there is nothing you can do on failure, short of calling
a back-up routine that uses fixed buffers.
So you handle fail conditions for the few large legitimate allocations,
which might run the computer out of memory, and abort on the rest.
The main cause of OOM are memory leaks, i.e. bugs, that cannot be
handled anyway. abort() is more dramatic than exit(). It indicates
that there is a problem and some action ought to be performed now.
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 24 '07 #15
rp*****@yahoo.com (Roland Pibinger) writes:
[...]
The discussion basically boils down to one question: Is OOM an error
that reasonably can and should be handled by the application or is it
a fatal error?
The 'fatal error' advocates have already shown how they tackle the
problem. Now it's time for the other camp to demonstrate how OOM can
be consistently _handled_ throughout the program ('return NULL;' is
not enough).
Who says it can be handled *consistently*?

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 24 '07 #16

"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
rp*****@yahoo.com (Roland Pibinger) writes:
[...]
>The discussion basically boils down to one question: Is OOM an error
that reasonably can and should be handled by the application or is it
a fatal error?
The 'fatal error' advocates have already shown how they tackle the
problem. Now it's time for the other camp to demonstrate how OOM can
be consistently _handled_ throughout the program ('return NULL;' is
not enough).

Who says it can be handled *consistently*?
That is part of the issue.
malloc() return NULL. The if condition following the malloc() is like a
yippy dog chasing a car. Now it's got an error, what is it going to do with
it?
--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jun 24 '07 #17
Roland Pibinger wrote:
On Sat, 23 Jun 2007 16:30:12 -0400, Eric Sosman wrote:
> Not all that strange. Half the programmers in the world
are below-average.

which is at least half-true.
> But if you follow Malcolm's Maxims, even the above-average
programmers will be helpless. Programs that deal with malloc()
failure in a significant way may be a minority, but those that
do it *need* to to do it. Malcolm argues, in essence, that
such programs should not be written in C.

The discussion basically boils down to one question: Is OOM an error
that reasonably can and should be handled by the application or is it
a fatal error?
The 'fatal error' advocates have already shown how they tackle the
problem. Now it's time for the other camp to demonstrate how OOM can
be consistently _handled_ throughout the program ('return NULL;' is
not enough).
Already mentioned a few times in this thread:

buff = malloc(image_size);
if (buff == NULL) {
fprintf (stderr, "Image too large (%lu) to paste\n",
(unsigned long)image_size);
return;
}
/* read image into buff, insert in current document */

Here's another I think has been referred to:

must_have_mem = malloc(how_much);
if (must_have_mem == NULL) {
fprintf (stderr, "Out of memory; shutting down\n");
save_snapshot(snapshot_file);
exit (EXIT_FAILURE);
}
/* store "must have" data in allocated memory */

And here's still another (I don't remember whether it's
cropped up in this thread yet):

void *getmem(size_t bytes) {
void *new = malloc(bytes);
if (new == NULL && bytes 0) {
fprintf (stderr, "Failed to allocate %lu bytes\n",
(unsigned long)bytes);
free (emergency_stash);
emergency_stash = NULL;
new = malloc(bytes);
if (new == NULL) {
fprintf (stderr, "You were warned ...!\n");
exit (EXIT_FAILURE);
}
fprintf (stderr, "Running on fumes: save your work "
"and exit soon!\n");
}
return NULL;
}

Even if out-of-memory is a "fatal error," it does not follow
that the program should have no opportunity to "die with dignity."
Have you made a will, Roland? If so, should the fact that many
people die intestate invalidate your will? If not, I certainly
don't want your intestacy to invalidate my will!

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 24 '07 #18
Malcolm McLean wrote:
>
"Roland Pibinger" <rp*****@yahoo.comwrote in message
news:46**************@news.utanet.at...
>On Sat, 23 Jun 2007 18:47:44 +0000, Richard Heathfield wrote:
>>The second problem is also quite easy to fix, and it's this - the
function calls exit(), thus taking the decision to quit the program out
of the hands of the programmer. Therefore, the programmer won't call
this function himself, and won't be able to call any other function in
the library that /does/ call it.

You can often see programs that check the return value of malloc but
you hardly (practically never) see any code that actually handles the
OOM (out-of-memory) condition (e.g. frees some pre-allocated memory).
Strange, isn't it?
Moreover, C libraries usually crash when the caller provides
insufficient resources or invalid arguments. In that sense abort() is
preferable to exit() for OOM.
Normally if you've written the program in such a way that it makes a lot
of trival allocations, there is nothing you can do on failure, short of
calling a back-up routine that uses fixed buffers.
So you handle fail conditions for the few large legitimate allocations,
which might run the computer out of memory, and abort on the rest.
That is so bass-ackwards it boggles the mind.

Here's the question: Does your program have in-memory state
that is valuable? If so, the proximate cause of the program's
trouble is irrelevant; what matters is the preservation of that
valuable state.
You can declare a global "world" pointer, and then in atexit try to save
the state of the program, but there are two problems.
... one being that abort doesn't run atexit callbacks ...
Firstly if the OS
won't give you a few hundred bytes, it might well not open files for you
either. Secondly, all the code has to be very carefully written so that
an allocation failure never causes the state to lose coherence.
Otherwise you will crash when you try to write a null pointer, or worse,
write an image that looks right but is in fact subtly corrupted.

So there really isn't an easy answer.
Let's avoid all hard problems; they demoralize the weak.
So if you use recursive subroutines you've already got one potential
source of crashes on malicious or excessive input. That reduces the
motivation to fix malloc(), because you can't guarantee correct
operation anyway.
And the janitor might unplug the computer to plug in the
floor polisher, or the fire sprinklers might open up and flood
the motherboard, or a meteorite might smash the computer to
tiny bits, or the Borg might teleport it away for assimilation.
Does the existence of Failure Mode A dissuade you from taking
any precautions against Failure Mode B? "I don't wear seat
belts in cars, because avian flu might kill me anyhow." Pfui!
--
Eric Sosman
es*****@acm-dot-org.invalid

Jun 24 '07 #19
rp*****@yahoo.com (Roland Pibinger) wrote:
# On Sat, 23 Jun 2007 16:30:12 -0400, Eric Sosman wrote:
# Not all that strange. Half the programmers in the world
# >are below-average.
#
# which is at least half-true.

Presumes a normal distribution. While many processes show normal
distribution of results, many processes also do not. Human
populations which are deliberately selected for some trait can
be signficantly skewed.

Hidden assumptions--the claymore mines of programming.

--
SM Ryan http://www.rawbw.com/~wyrmwif/
I love the smell of commerce in the morning.
Jun 24 '07 #20
Malcolm McLean wrote:
"Keith Thompson" <ks***@mib.orgwrote in message
>rp*****@yahoo.com (Roland Pibinger) writes:

[...]
>>The discussion basically boils down to one question: Is OOM an
error that reasonably can and should be handled by the
application or is it a fatal error? The 'fatal error' advocates
have already shown how they tackle the problem. Now it's time
for the other camp to demonstrate how OOM can be consistently
_handled_ throughout the program ('return NULL;' is not enough).

Who says it can be handled *consistently*?

That is part of the issue. malloc() return NULL. The if condition
following the malloc() is like a yippy dog chasing a car. Now it's
got an error, what is it going to do with it?
The answer is simple. The model for calling malloc is:

if (!(p = malloc(N * sizeof *p))) callerrorrecoveryetc();
else { /* all is well */
....
}

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 24 '07 #21

"Eric Sosman" <es*****@acm-dot-org.invalidwrote in message
>
>So if you use recursive subroutines you've already got one potential
source of crashes on malicious or excessive input. That reduces the
motivation to fix malloc(), because you can't guarantee correct operation
anyway.

And the janitor might unplug the computer to plug in the
floor polisher, or the fire sprinklers might open up and flood
the motherboard, or a meteorite might smash the computer to
tiny bits, or the Borg might teleport it away for assimilation.
Does the existence of Failure Mode A dissuade you from taking
any precautions against Failure Mode B? "I don't wear seat
belts in cars, because avian flu might kill me anyhow." Pfui!
Yes. That's actually a fundamental observation.

Let's say we've got a failure rate of 10% per annum. By eliminating cause B,
we can reduce that to 9.9%. Unfortunately the cost of the product goes up
10% as result. Almost certainly it is not worth it.
Now imagine the failure rate is 1% per annnum. By eliminating cause B, we
can reduce that to 0.9%. Again, cost rises by 10%.
In the final scenario, failure rate is 0.1% per annum. By eliminating cause
B we can reduc that to 0.01% per annum, again for the same price.

In the middle scenario eliminating feature B is quite attractive. In the
last one, almost certainly you will want to do it, because the you can claim
a nearly failure-free product. The only exception would be if customers care
about price and not about quality at all - a T-shirt with a slogan on it,
for instance.

The value of eliminating an error goes up as it accounts for a greater
proportion of overall errors.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 24 '07 #22
On Sun, 24 Jun 2007 09:12:06 -0400, Eric Sosman wrote:
Already mentioned a few times in this thread:

buff = malloc(image_size);
if (buff == NULL) {
fprintf (stderr, "Image too large (%lu) to paste\n",
(unsigned long)image_size);
return;
}
/* read image into buff, insert in current document */

Here's another I think has been referred to:

must_have_mem = malloc(how_much);
if (must_have_mem == NULL) {
fprintf (stderr, "Out of memory; shutting down\n");
save_snapshot(snapshot_file);
exit (EXIT_FAILURE);
}
/* store "must have" data in allocated memory */
The above approachs do not handle OOM ('handle' in the meaning of
'remedy'). They pass the problem to the caller or exit the program.
The second approach would soon be refactored into a malloc_or_exit()
function.
And here's still another (I don't remember whether it's
cropped up in this thread yet):

void *getmem(size_t bytes) {
void *new = malloc(bytes);
if (new == NULL && bytes 0) {
fprintf (stderr, "Failed to allocate %lu bytes\n",
(unsigned long)bytes);
free (emergency_stash);
emergency_stash = NULL;
new = malloc(bytes);
if (new == NULL) {
fprintf (stderr, "You were warned ...!\n");
exit (EXIT_FAILURE);
}
fprintf (stderr, "Running on fumes: save your work "
"and exit soon!\n");
}
return NULL;
}
This actually is an attempt to cope with OOM. But, as demonstrated,
the possibilities are very limited. You cannot do much when the
primary source of your program is exhausted.
Even if out-of-memory is a "fatal error," it does not follow
that the program should have no opportunity to "die with dignity."
Have you made a will, Roland?
I consider to use

void *xmalloc (size_t bytes) {
return getmem (bytes);
}

which, IMHO, elegently combines the best of all approaches posted so
far in this thread ;-)

In general I prefer: 'Repair what you can — but when you must fail,
fail noisily and as soon as possible'
(http://www.catb.org/~esr/writings/ta...html#id2878538)
--
Roland Pibinger
"Software development has been, is, and will remain fundamentally hard" - Grady Booch
Jun 24 '07 #23
"Malcolm McLean" <re*******@btinternet.comwrites:
"Keith Thompson" <ks***@mib.orgwrote in message
news:ln************@nuthaus.mib.org...
>rp*****@yahoo.com (Roland Pibinger) writes:
[...]
>>The discussion basically boils down to one question: Is OOM an error
that reasonably can and should be handled by the application or is it
a fatal error?
The 'fatal error' advocates have already shown how they tackle the
problem. Now it's time for the other camp to demonstrate how OOM can
be consistently _handled_ throughout the program ('return NULL;' is
not enough).

Who says it can be handled *consistently*?
That is part of the issue.
malloc() return NULL. The if condition following the malloc() is like
a yippy dog chasing a car. Now it's got an error, what is it going to
do with it?
The "yippy dog chasing a car" analogy applies equally well when
malloc() returns a non-null result. Now you've got a valid pointer to
allocated memory; what are you going to do with it?

The answer is: do whatever makes sense in the context of the program.

Determining the answers to such questions is called "programming";
it's a non-trivial activity.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 24 '07 #24
Roland Pibinger wrote:
On Sun, 24 Jun 2007 09:12:06 -0400, Eric Sosman wrote:
> Already mentioned a few times in this thread:

buff = malloc(image_size);
if (buff == NULL) {
fprintf (stderr, "Image too large (%lu) to paste\n",
(unsigned long)image_size);
return;
}
/* read image into buff, insert in current document */

Here's another I think has been referred to:

must_have_mem = malloc(how_much);
if (must_have_mem == NULL) {
fprintf (stderr, "Out of memory; shutting down\n");
save_snapshot(snapshot_file);
exit (EXIT_FAILURE);
}
/* store "must have" data in allocated memory */

The above approachs do not handle OOM ('handle' in the meaning of
'remedy'). They pass the problem to the caller or exit the program.
The second approach would soon be refactored into a malloc_or_exit()
function.
Where did "remedy" creep into the picture? Both of the
above sketches acknowledge that the program is unable to
carry out some operation in the absence of sufficient memory,
but both "handle" the lack by taking a substitute action.
The first might be found in something like an interactive
editor, where the user gets a chance to say "Forty gig? Oh,
right, that's the original super-high-resolution file, not
the low-res image I actually intended to use." The second
does something that seems to have escaped your notice, to
wit, it calls save_snapshot() to preserve the valuable state
before pulling the plug. Neither strategy could be implemented
if malloc() just decided to blow up the program on its own whim.
> And here's still another (I don't remember whether it's
cropped up in this thread yet):

void *getmem(size_t bytes) {
void *new = malloc(bytes);
if (new == NULL && bytes 0) {
fprintf (stderr, "Failed to allocate %lu bytes\n",
(unsigned long)bytes);
free (emergency_stash);
emergency_stash = NULL;
new = malloc(bytes);
if (new == NULL) {
fprintf (stderr, "You were warned ...!\n");
exit (EXIT_FAILURE);
}
fprintf (stderr, "Running on fumes: save your work "
"and exit soon!\n");
}
return NULL;
}

This actually is an attempt to cope with OOM. But, as demonstrated,
the possibilities are very limited. You cannot do much when the
primary source of your program is exhausted.
How much you can do depends on how much you have made
provision for. That in turn depends on your analysis of how
much memory the program requires for "last gasp" operations.
At a PPOE this feature of the program received regular Q/A:
a whole bunch of state was loaded into memory, and then the
test harness induced artificial malloc failures; if the
program's emergency stash wasn't enough to sustain the last
gasp, a bug got filed.
> Even if out-of-memory is a "fatal error," it does not follow
that the program should have no opportunity to "die with dignity."
Have you made a will, Roland?

I consider to use

void *xmalloc (size_t bytes) {
return getmem (bytes);
}

which, IMHO, elegently combines the best of all approaches posted so
far in this thread ;-)

In general I prefer: 'Repair what you can — but when you must fail,
fail noisily and as soon as possible'
(http://www.catb.org/~esr/writings/ta...html#id2878538)
"When you must fail" is not blanket advice to give up
the ghost at the first sign of adversity. You might also
note that all three of the sketches I provided made noise.

--
Eric Sosman
es*****@acm-dot-org.invalid
Jun 24 '07 #25
On 23 Jun, 20:06, "Malcolm McLean" <regniz...@btinternet.comwrote:
"Richard Heathfield" <r...@see.sig.invalidwrote in message
news:kb******************************@bt.com...
Malcolm McLean said:
<snip>
In which case would call regular malloc()
However you are doubling the cost of the software with that strategy, all
because a 2GB machine might refuse to give a few hundred bytes of memory. If
it is running a life-support machine, fair enough, but most software
doesn't.

On the other hand you could argue that xmalloc() is a bad idea, because no
library that uses it could ever find its way into a life-support machine.
On the other hand, you could argue that the life support machine is more
likely to blow a fuse than to exit in xmalloc(), so you need a backup
anyway.
I assume "life-support machine" is a meta syntactic variable for
safety/mission critical software.

Just how important does a program have to be before its given
LSM status and doesn't crash without doing *some* error handling?

- actual life support machine
- anti-lock brakes
- communications equipment used by emergency services
- communications equipment used to report aircraft movements
- your bank account
- your word-processor
- your central heating system
- the game you've been playing for a week
- unix filter
- post to clc
--
Nick Keighley
Jun 25 '07 #26
Ian Collins <ia******@hotmail.comwrote:
It could be enhanced by providing a (cough) global failure function, say
xmalloc_failure, that gets called when malloc returns NULL:
void* (*xmalloc_failure)(size_t) = &default_xmalloc_failure;
Why make it a global function?

static void* (*xmalloc_failure)( size_t );

void register_xmalloc_failfunc( void* (*failfunc)(size_t) ) {
xmalloc_failure = failfunc;
}

There's no need to expose xmalloc_failure or default_xmalloc_failure
to client code, and I would personally prefer not to.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 25 '07 #27
Malcolm McLean <re*******@btinternet.comwrote:
void *xmalloc(int sz)
{
assert(sz >= 0);
if(sz == 0)
sz = 1;
All right, I give up. Why should xmalloc() quietly prohibit zero-byte
allocations? If a client asks for zero bytes, why not just *give* it
zero bytes? For that matter, given the above code, what is wrong with

if( sz <= 0 ) {
sz=1;
}

? You seem to be assuming that xmalloc()'s clients aren't very bright
anyway.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 25 '07 #28
Harald van D?k <tr*****@gmail.comwrote:
malloc(0) can make sense, but is allowed by the standard to either return
NULL or non-NULL on success. Because of this, xmalloc(0) calls malloc(1) so
that a successfull allocation will always return non-NULL.
I take about half of this point. While the code as written did indeed
need to distinguish between failure to allocate non-zero bytes, and
successful allocation of zero bytes (a fact which I missed), it's not
clear to me that xmalloc()'s clients gain anything by essentially
having all calls to malloc(0) replaced by malloc(1). The pointer
returned by malloc(0), if not NULL, can't be used to access an object
anyway, so from xmalloc()'s clients' perspectives, it doesn't much
matter whether xmalloc(0) returns NULL or not:

void *xmalloc( size_t sz ) {
if( sz == 0 ) {
return NULL;
}
/* ... */
}

May as well save the call to malloc(0), if you ask me.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 25 '07 #29
Christopher Benson-Manica wrote:
Harald van D?k <tr*****@gmail.comwrote:
>malloc(0) can make sense, but is allowed by the standard to either return
NULL or non-NULL on success. Because of this, xmalloc(0) calls malloc(1)
so that a successfull allocation will always return non-NULL.

I take about half of this point. While the code as written did indeed
need to distinguish between failure to allocate non-zero bytes, and
successful allocation of zero bytes (a fact which I missed), it's not
clear to me that xmalloc()'s clients gain anything by essentially
having all calls to malloc(0) replaced by malloc(1). The pointer
returned by malloc(0), if not NULL, can't be used to access an object
anyway, so from xmalloc()'s clients' perspectives, it doesn't much
matter whether xmalloc(0) returns NULL or not:

void *xmalloc( size_t sz ) {
if( sz == 0 ) {
return NULL;
}
/* ... */
}

May as well save the call to malloc(0), if you ask me.
It depends on the project. Sometimes it matters to have different calls to
malloc(0) return values that do not compare equal, sometimes it doesn't.
Jun 25 '07 #30
On Jun 23, 8:47 pm, Richard Heathfield <r...@see.sig.invalidwrote:
[snip]
>
What malloc() problem? And this "solution" suffers from the same problem
as any other "solution" of the same kind - it's no earthly use in a
library,
and libraries are where malloc calls belong.
Does that mean that malloc calls not are to be used in regular
programs? If yes, what should one use instead? Get some library
or write one by oneself?

Also what does the x mean in xmalloc? Iv'e seen it numerous of
times in sources.

Thanks!

Jun 25 '07 #31
ba******@hushmail.com said:
On Jun 23, 8:47 pm, Richard Heathfield <r...@see.sig.invalidwrote:
[snip]
>>
What malloc() problem? And this "solution" suffers from the same
problem as any other "solution" of the same kind - it's no earthly
use in a library,
and libraries are where malloc calls belong.
Does that mean that malloc calls not are to be used in regular
programs?
Ah, I see that my comment may have been misleading. No, I don't wish to
suggest that you should *never* use malloc except in libraries. It's
just that it has been my experience that, once a program has been
through the mill and been refactored and rejigged and generally beaten
into shape, the malloc stuff tends to end up in a separate module that
is eminently suitable for being reused in other programs.

In other words, I was just describing what *usually* happens, not what
*must* happen.

<snip>
Also what does the x mean in xmalloc? Iv'e seen it numerous of
times in sources.
No idea. And I don't really care either, since I never use it.

--
Richard Heathfield <http://www.cpax.org.uk>
Email: -www. +rjh@
Google users: <http://www.cpax.org.uk/prg/writings/googly.php>
"Usenet is a strange place" - dmr 29 July 1999
Jun 25 '07 #32
Christopher Benson-Manica wrote:
Malcolm McLean <re*******@btinternet.comwrote:
>void *xmalloc(int sz) {
> assert(sz >= 0);
if(sz == 0)
sz = 1;

All right, I give up. Why should xmalloc() quietly prohibit
zero-byte allocations? If a client asks for zero bytes, why not
just *give* it zero bytes? For that matter, given the above code,
Because the C-standard allows a malloc call for zero bytes to
return a NULL pointer, and you can't tell that from a failure. For
this (and other) reasons my nmalloc increments a zero allocation
size to 1, and then allocates accordingly. Same for realloc.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 25 '07 #33
Harald van D?k <tr*****@gmail.comwrote:
It depends on the project. Sometimes it matters to have different calls to
malloc(0) return values that do not compare equal, sometimes it doesn't.
And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 26 '07 #34
Christopher Benson-Manica wrote:
Harald van D?k <tr*****@gmail.comwrote:
>It depends on the project. Sometimes it matters to have different calls
to malloc(0) return values that do not compare equal, sometimes it
doesn't.

And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?
Then the xmalloc helper function changes the request for 0 bytes by one for
1 byte, and all is fine.
Jun 26 '07 #35
Harald van D?k <tr*****@gmail.comwrote:
Christopher Benson-Manica wrote:
And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?
Then the xmalloc helper function changes the request for 0 bytes by one for
1 byte, and all is fine.
My point is that malloc() does not behave like that, and so at that
point xmalloc() becomes more than a drop-in replacement for malloc().
At that point the function should at the least be renamed so that it
is clear that it cannot be replaced by malloc() without verifying that
a program does not rely on this IMHO subtle behavior of xmalloc().

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 26 '07 #36
Christopher Benson-Manica wrote:
Harald van D?k <tr*****@gmail.comwrote:
>Christopher Benson-Manica wrote:
And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?
>Then the xmalloc helper function changes the request for 0 bytes by one
for 1 byte, and all is fine.

My point is that malloc() does not behave like that, and so at that
point xmalloc() becomes more than a drop-in replacement for malloc().
At that point the function should at the least be renamed so that it
is clear that it cannot be replaced by malloc() without verifying that
a program does not rely on this IMHO subtle behavior of xmalloc().
Well, yes, just like you can't blindly replace xmalloc calls with malloc
calls without adding NULL checks on every call.
Jun 26 '07 #37
Christopher Benson-Manica <at***@vinland.freeshell.orgwrites:
Harald van D?k <tr*****@gmail.comwrote:
>Christopher Benson-Manica wrote:
And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?
>Then the xmalloc helper function changes the request for 0 bytes by one for
1 byte, and all is fine.

My point is that malloc() does not behave like that, and so at that
point xmalloc() becomes more than a drop-in replacement for malloc().
At that point the function should at the least be renamed so that it
is clear that it cannot be replaced by malloc() without verifying that
a program does not rely on this IMHO subtle behavior of xmalloc().
The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.

The fact that xmalloc differs from malloc is made clear enough by the
fact that it has a different name.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #38
Keith Thompson wrote On 06/26/07 00:05,:
Christopher Benson-Manica <at***@vinland.freeshell.orgwrites:
>>Harald van D?k <tr*****@gmail.comwrote:
>>>Christopher Benson-Manica wrote:

And if it matters, and if the implementation chooses to always return
NULL for malloc(0), what then?
>>>Then the xmalloc helper function changes the request for 0 bytes by one for
1 byte, and all is fine.

My point is that malloc() does not behave like that, and so at that
point xmalloc() becomes more than a drop-in replacement for malloc().
At that point the function should at the least be renamed so that it
is clear that it cannot be replaced by malloc() without verifying that
a program does not rely on this IMHO subtle behavior of xmalloc().


The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.
malloc() is permitted to call exit()? When did
that happen?

--
Er*********@sun.com
Jun 26 '07 #39
On Mon, 25 Jun 2007 14:12:15 -0700, ba******@hushmail.com wrote:
>Also what does the x mean in xmalloc? Iv'e seen it numerous of
times in sources.
eXtended malloc?
--
Roland Pibinger
"The best software is simple, elegant, and full of drama" - Grady Booch
Jun 26 '07 #40
ba******@hushmail.com writes:
Also what does the x mean in xmalloc? Iv'e seen it numerous of
times in sources.
"exit" maybe? Typical implementations call exit if memory cannot
be obtained.
--
"I'm not here to convince idiots not to be stupid.
They won't listen anyway."
--Dann Corbit
Jun 26 '07 #41
Eric Sosman <Er*********@sun.comwrites:
Keith Thompson wrote On 06/26/07 00:05,:
>Christopher Benson-Manica <at***@vinland.freeshell.orgwrites:
>>>Harald van D?k <tr*****@gmail.comwrote:

Christopher Benson-Manica wrote:

>And if it matters, and if the implementation chooses to always return
>NULL for malloc(0), what then?

Then the xmalloc helper function changes the request for 0 bytes by one for
1 byte, and all is fine.

My point is that malloc() does not behave like that, and so at that
point xmalloc() becomes more than a drop-in replacement for malloc().
At that point the function should at the least be renamed so that it
is clear that it cannot be replaced by malloc() without verifying that
a program does not rely on this IMHO subtle behavior of xmalloc().


The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.

malloc() is permitted to call exit()? When did
that happen?
Whoops, never mind.

I think what I meant is that the behavior of xmalloc *when it
succeeds* is consistent with the allowed behavior of malloc.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #42
Keith Thompson wrote:
The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.
This portable code:

http://www.mindspring.com/~pfilandr/...ine/get_line.c

has a malloc(0) call,
and does assume that a non-null result may be returned.

--
pete
Jun 26 '07 #43
Eric Sosman wrote:
Keith Thompson wrote On 06/26/07 00:05,:
.... snip ...
>>
The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0)
can return a non-null result.

malloc() is permitted to call exit()? When did that happen?
He must be using Microsoft compilers :-)

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 26 '07 #44
pete <pf*****@mindspring.comwrites:
Keith Thompson wrote:
>The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.

This portable code:

http://www.mindspring.com/~pfilandr/...ine/get_line.c

has a malloc(0) call,
and does assume that a non-null result may be returned.
It looks like I managed to pack a lot of ambiguity into that sentence.

What I meant is that no portable code can assume that a successful
malloc(0) will always return a non-null result; if malloc(0) returns
NULL, it may or may not indicate that you've run out of memory.

The xmalloc implementation being discussed behaves very differently
from malloc on failure (it aborts the program). The issue is that
xmalloc(0) invokes malloc(1). That particular feature doesn't prevent
xmalloc from being a drop-in replacement for malloc (though aborting
the program certainly does). A valid implementation may treat
malloc(0) as exactly equivalent to malloc(1). malloc(0) is
*permitted* to return NULL even if there's plenty of memory available;
no portable code can assume either that malloc takes advantage of this
permission, or that it doesn't.

Due to the flexibility in the standard's requirement for malloc(0),
xmalloc has to translate malloc(0) into malloc(1); otherwise, there'd
be no way for xmalloc(0) to decide whether to abort the program. (I'm
assuming here that aborting the program on failure is a requirement
for xmalloc.)

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 26 '07 #45
pete wrote:
Keith Thompson wrote:
>The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0)
can return a non-null result.

This portable code:

http://www.mindspring.com/~pfilandr/...ine/get_line.c

has a malloc(0) call,
and does assume that a non-null result may be returned.
Then that code is not portable.

--
<http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
<http://www.securityfocus.com/columnists/423>
<http://www.aaxnet.com/editor/edit043.html>
cbfalconer at maineline dot net

--
Posted via a free Usenet account from http://www.teranews.com

Jun 26 '07 #46
CBFalconer <cb********@yahoo.comwrites:
pete wrote:
>Keith Thompson wrote:
>>The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0)
can return a non-null result.

This portable code:

http://www.mindspring.com/~pfilandr/...ine/get_line.c

has a malloc(0) call,
and does assume that a non-null result may be returned.

Then that code is not portable.
Not at all. It assumes that a non-null result *may* be returned; more
precisely, it allows for that possibility.

Here's the relevant snippet (the INITIAL_BUFFER_SIZE macro expands to 0):

[...]
size = INITIAL_BUFFER_SIZE;
buff = malloc(size);
if (buff == NULL && size != 0) {
[...]

It only assumes failure if malloc returns NULL with a non-zero
argument. If malloc(0) returns NULL, it can't know whether it
succeeded or failed; I assume (without having studied the code) that
it doesn't care.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jun 27 '07 #47
Keith Thompson <ks***@mib.orgwrote:
The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0) can
return a non-null result.
Right. That's why I took issue with this statement from upthread:

Harald van D?k <tr*****@gmail.comwrote:
It depends on the project. Sometimes it matters to have different calls
to malloc(0) return values that do not compare equal, sometimes it
doesn't.
I hope I'm not exceeding the maximum permitted pedantry level here,
but it seems worthwhile to bring it up.
The fact that xmalloc differs from malloc is made clear enough by the
fact that it has a different name.
I suppose I concede the point, but I'd name it something else myself.

--
C. Benson Manica | I *should* know what I'm talking about - if I
cbmanica(at)gmail.com | don't, I need to know. Flames welcome.
Jun 27 '07 #48
Keith Thompson wrote:
>
CBFalconer <cb********@yahoo.comwrites:
pete wrote:
Keith Thompson wrote:

The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0)
can return a non-null result.

This portable code:

http://www.mindspring.com/~pfilandr/...ine/get_line.c

has a malloc(0) call,
and does assume that a non-null result may be returned.
Then that code is not portable.

Not at all. It assumes that a non-null result *may* be returned; more
precisely, it allows for that possibility.

Here's the relevant snippet (the INITIAL_BUFFER_SIZE macro expands to 0):

[...]
size = INITIAL_BUFFER_SIZE;
buff = malloc(size);
if (buff == NULL && size != 0) {
[...]

It only assumes failure if malloc returns NULL with a non-zero
argument. If malloc(0) returns NULL, it can't know whether it
succeeded or failed; I assume (without having studied the code) that
it doesn't care.
It doesn't care.
The result of the malloc call
becomes an argument in either a call to realloc,
or a call to free

--
pete
Jun 27 '07 #49

"CBFalconer" <cb********@yahoo.comwrote in message
news:46***************@yahoo.com...
Eric Sosman wrote:
>Keith Thompson wrote On 06/26/07 00:05,:
... snip ...
>>>
The behavior of xmalloc is still *consistent* with the allowed
behavior of malloc; no portable code can assume that malloc(0)
can return a non-null result.

malloc() is permitted to call exit()? When did that happen?

He must be using Microsoft compilers :-)
I accidentally created an infinite loop making a small allocations with
Microsoft's free C compiler.
It hung the entire machine for about two minutes, but allowed me to kill the
offending process, and recovered after about another minute.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm

Jun 27 '07 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

3
by: Petr Pavlu | last post by:
Hello, I have two questions how the functions should be written. I read the FAQ but didn't find any answer. If there is any please point me out. I. Cleanup code Consider I have to open file1,...
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.