468,490 Members | 2,595 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,490 developers. It's quick & easy.

When to check the return value of malloc

Howdy,

I was reflecting recently on malloc.

Obviously, for tiny allocations like 20 bytes to strcpy a filename or
something, there's no point putting in a check on the return value of
malloc.

OTOH, if you're allocating a gigabyte for a large array, this might
fail, so you should definitely check for a NULL return.

So somewhere in between these extremes, there must be a point where you
stop ignoring malloc's return value, and start checking it.

Where do people draw this line? I guess it depends on the likely system
the program will be deployed on, but are there any good rule-of-thumbs?

Rgds,
MJ

Jan 18 '08
173 6930
On Sat, 19 Jan 2008 12:11:41 -0600, CBFalconer wrote
(in article <47***************@yahoo.com>):
That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;
What?
if (!(res = malloc(s))) {
fputs("malloc() failed\n", stderr);
exit(EXIT_FAILURE); /* optional */
}
return res;
}

which can leave the exit decision to the caller. It also makes the
return of NULL a positive indication of failure.



--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Jan 20 '08 #51
Malcolm McLean wrote:
"Eric Sosman" <es*****@ieee-dot-org.invalidwrote:
>Malcolm McLean wrote:
>>>
Typically something between 33% to 50% of code will be there to
handle malloc() failures, in constructor-like C functions.

Please cite the research that measured this surprising figure.

Just check my website. Virtually all the files are written in
"object style". That is to say, there is a function with the
same name as the public structure, though in lower case, and a
corresponding kill function. There are also opaque method
functions which manipulate the structures.
There are other possible conclusions. One is the horrible
inefficiency of "object style". Another is the possible flaws in
your coding style.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 20 '08 #52
Malcolm McLean wrote:
>
.... snip ...
>
If you've got better semantics for xmalloc, then by all means
share them. I don't think it's an ideal solution at all. It's the
least bad solution to the problem of trivial requests failing
I've been able to devise so far.
What about the accurate:

if (!(p = malloc(szneeded * sizof *p)))
callAppropriateRecovery(szneeded, &p);
.... /* all well if recovery works */

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 20 '08 #53
Ian Collins wrote:
CBFalconer wrote:
>Eric Sosman wrote:
>> 2) The test should be `if (!res && s)'.

That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

Why?
That converts a request for 0 bytes to a request for 1 byte, and
avoids the return of NULL when malloc has not failed (an option,
according to the std).

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 20 '08 #54
Randy Howard wrote:
CBFalconer wrote
>That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

What?
Leaving s in the range 1 .. SIZE_MAX.
>
> if (!(res = malloc(s))) {
fputs("malloc() failed\n", stderr);
exit(EXIT_FAILURE); /* optional */
}
return res;
}

which can leave the exit decision to the caller. It also makes the
return of NULL a positive indication of failure.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.
--
Posted via a free Usenet account from http://www.teranews.com

Jan 20 '08 #55
On Sat, 19 Jan 2008 23:49:22 -0500, CBFalconer wrote:
That converts a request for 0 bytes to a request for 1 byte, and avoids
the return of NULL when malloc has not failed (an option, according to
the std).
Another interpretation is that the standard does not allow a null pointer
to be returned except as a failure indicator, but that it allows malloc
to unconditionally fail if the requested size is zero. The end result is
the same for malloc (which is probably why the standard doesn't specify
which is correct), but this interpretation is consistent with realloc,
where a null pointer indicates failure and does not cause the old object
to be freed, even if the new size is zero.
Jan 20 '08 #56
>I was reflecting recently on malloc.
>
Obviously, for tiny allocations like 20 bytes to strcpy a filename or
something, there's no point putting in a check on the return value of
malloc.
There certainly IS a point in checking the return value of malloc()
EVERY SINGLE TIME. If the program fails and you don't have a check
in there, YOU get the blame. If the program fails and you DO have
a check in there that prints an appropriate message, you can blame
someone else (like the guy that spec'd the system or someone running
a memory hog on it). Your job may depend on this.

>OTOH, if you're allocating a gigabyte for a large array, this might
fail, so you should definitely check for a NULL return.
If you're allocating a gigabyte in 20 byte pieces, it might fail
at some point.
>So somewhere in between these extremes, there must be a point where you
stop ignoring malloc's return value, and start checking it.

Where do people draw this line? I guess it depends on the likely system
the program will be deployed on, but are there any good rule-of-thumbs?
Don't bother checking the return value of malloc(0) (where the zero
value is a constant). The easist way to deal with this is to never
call malloc(0) in the first place.

Anything more than that, you should check.

Jan 20 '08 #57
CBFalconer wrote:
Ian Collins wrote:
>CBFalconer wrote:
>>Eric Sosman wrote:
2) The test should be `if (!res && s)'.
That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;
Why?

That converts a request for 0 bytes to a request for 1 byte, and
avoids the return of NULL when malloc has not failed (an option,
according to the std).
I still think it best to force fail or make the user provide a handler
for zero byte requests on the grounds they are probably an error.

One could argue that by invoking implementation defined behaviour from
malloc, it is always an error (or at least not portable).

--
Ian Collins.
Jan 20 '08 #58
On Sat, 19 Jan 2008 22:55:01 -0600, CBFalconer wrote
(in article <47***************@yahoo.com>):
Randy Howard wrote:
>CBFalconer wrote
>>That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

What?

Leaving s in the range 1 .. SIZE_MAX.
Yeah, but with a name like xmalloc(), you don't expect munging of the
behavior. If you called it something like
mymallocthatfixessillyrequests() maybe. I'd much rather have it do
what I ask of it, than that, and certainly not do so quietly.

--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Jan 20 '08 #59
Ian Collins <ia******@hotmail.comwrites:
I still think it best to force fail or make the user provide a handler
for zero byte requests on the grounds they are probably an error.
I disagree. In my own experience, some algorithms on arrays
gracefully degrade to the case of 0-length arrays. For
implementing such algorithms it is valuable to not have to insert
otherwise gratuitous checks for 0.
--
"This is a wonderful answer.
It's off-topic, it's incorrect, and it doesn't answer the question."
--Richard Heathfield
Jan 20 '08 #60
Randy Howard <ra*********@FOOverizonBAR.netwrites:
On Sat, 19 Jan 2008 22:55:01 -0600, CBFalconer wrote
(in article <47***************@yahoo.com>):
>Randy Howard wrote:
>>CBFalconer wrote

That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

What?

Leaving s in the range 1 .. SIZE_MAX.

Yeah, but with a name like xmalloc(), you don't expect munging of the
behavior. If you called it something like
mymallocthatfixessillyrequests() maybe. I'd much rather have it do
what I ask of it, than that, and certainly not do so quietly.
It still does what you ask of it, since the successful return
value of malloc(0) depends on the implementation: it may be a
null pointer or a unique pointer value that may not be
dereferenced. There seems to be a large contingent in the C
world in favor of the latter behavior, and this is not the first
xmalloc implementation that I have seen enforcing it.
--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
Jan 20 '08 #61
On Sun, 20 Jan 2008 01:42:28 -0600, Ben Pfaff wrote
(in article <87************@blp.benpfaff.org>):
Randy Howard <ra*********@FOOverizonBAR.netwrites:
>On Sat, 19 Jan 2008 22:55:01 -0600, CBFalconer wrote
(in article <47***************@yahoo.com>):
>>Randy Howard wrote:
CBFalconer wrote

That is more easily handled by:
>
void *xmalloc(size_t s) {
void *res;
>
if (!s) s++;

What?

Leaving s in the range 1 .. SIZE_MAX.

Yeah, but with a name like xmalloc(), you don't expect munging of the
behavior. If you called it something like
mymallocthatfixessillyrequests() maybe. I'd much rather have it do
what I ask of it, than that, and certainly not do so quietly.

It still does what you ask of it, since the successful return
value of malloc(0) depends on the implementation: it may be a
null pointer or a unique pointer value that may not be
dereferenced. There seems to be a large contingent in the C
world in favor of the latter behavior, and this is not the first
xmalloc implementation that I have seen enforcing it.
What I was aiming at, but I didn't do very well, was I'd probably
rather have it spit out a log file entry or perhaps something on screen
if I called with size of 0 than quietly do something different, because
most of the time, I'd want to know that this was happening, not have it
quietly done without realizing it.

This seems like it might have some short term benefits, but make
debugging something really flaky actually harder in the long run. To
each his own.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Jan 20 '08 #62
Ben Pfaff wrote:
Ian Collins <ia******@hotmail.comwrites:
>I still think it best to force fail or make the user provide a handler
for zero byte requests on the grounds they are probably an error.

I disagree. In my own experience, some algorithms on arrays
gracefully degrade to the case of 0-length arrays. For
implementing such algorithms it is valuable to not have to insert
otherwise gratuitous checks for 0.
But the original example did check for zero. I was merely proposing an
alternative to blindly changing the requested size to one. A user
provided handler can take into account the implementation's behaviour,
if required.

--
Ian Collins.
Jan 20 '08 #63
Ian Collins wrote:
CBFalconer wrote:
>Eric Sosman wrote:
>> 2) The test should be `if (!res && s)'.

That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

Why?
I'd offer another alternative that was pointed out to me in this thread:

p = malloc(s);
if(!p && s!=0)
failure().

The whole point of xmalloc() is that it either succeeds or aborts execution.
Now, since malloc(0) may or may not return NULL, that alone can't be taken
as indicator for failure in that corner case.

However, I think the agreed-on semantics of xmalloc are that you can
access 's' bytes starting at the returned pointer. Now, if 's' is zero, the
actual value that is returned doesn't matter[1], because effectively you
can only access zero bytes starting at that address. Using this allows
pretty uniform code for allocating arrays, no matter what their size is.
Since xmalloc checks against allocation failure and a zero size implicitly
guards you (provided proper use) against accessing this empty array, it
doesn't matter if you return NULL or some dummy value or change the
allocation size to one.

In that light, I'd even say that xmalloc should start like this:

if(s==0)
return NULL;
void* p=malloc(s);
...

The simple rationale is that dynamic allocations are typically expensive, so
avoiding them is worthwhile.
There is one caveat though: IIRC, quite a few implementations choke on
free(NULL), even more than those that choke on malloc(0). This might have
to be taken into account when porting to other platforms. It might be
easiest to change xmalloc() to always return at least one byte there.
Otherwise, you either have to check before calling free() or provide an
additional xfree() which behaves correctly.

The only case I can imagine this to fail is this kind of code:

// old version
p = malloc(s);
if(!p)
return ENOMEM;
// new version
p = xmalloc(s);
assert(p);// make sure xmalloc works

Both versions are in fact broken and their misbehaviour is not an indicator
of a broken xmalloc() implementation. The problem is that they both don't
take the weird malloc(0) behaviour into account. The correct code is this:

// old version
p = malloc(s);
if(!p && s!=0)
return ENOMEM;
// new version
p = xmalloc(s);
assert(p || s==0);// make sure xmalloc works

In my eyes, the assert() should be removed altogether, it only serves to
further clutter the code. Rather, I'd move the assert() into the
implementation of xmalloc().

Uli

[1] I'm aware of the fact that doing anything with uninitialised (random)
pointers is undefined.
Jan 20 '08 #64
Ulrich Eckhardt wrote:
<snip>
In that light, I'd even say that xmalloc should start like this:

if(s==0)
return NULL;
void* p=malloc(s);
...

The simple rationale is that dynamic allocations are typically
expensive, so avoiding them is worthwhile.
Well, any decent implementation will do that _first thing inside_ malloc(),
so the overhead would be that of a function call, no big deal.
There is one caveat though: IIRC, quite a few implementations choke on
free(NULL), even more than those that choke on malloc(0).
Neither is allowed to a conforming implementation.

free() has to take anything malloc() might return, that includes NULL and
malloc(0) is explictly allowed, and allthough it does have an implementation
defined behavoir, there are two choices allowed and choking on it is not
amongst them.

Bye, Jojo
Jan 20 '08 #65
Army1987 <ar******@NOSPAM.itwrites:
Keith Thompson wrote:
>There's an old saying: Never check for an error condition you don't
know how to handle.

But if you can't figure out what to do, you can always just terminate
the program. It's not necessarily the best thing you can do, but it's
the second simplest, and it's almost certainly better than the
simplest (ignoring the error).

Well, I don't usually check the result of a call such as
fprintf(stderr, "Can't frobnicate %s: %s\n", frob, strerror(errno)),
because I don't know what should I do if it failed, but I don't think that
just terminating the program would be a good idea (unless I were going to
terminate it right after the fprintf regardless of its success, that is).
I was referring specifically to malloc() failures.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 20 '08 #66
"Gordon Burditt" <go***********@burditt.orgwrote in message
news:13*************@corp.supernews.com...
I was reflecting recently on malloc.

Obviously, for tiny allocations like 20 bytes to strcpy a filename or
something, there's no point putting in a check on the return value of
malloc.

There certainly IS a point in checking the return value of malloc()
EVERY SINGLE TIME. If the program fails and you don't have a check
in there, YOU get the blame...
If there are a lot of these malloc()s bunched together, all these checks can
get very untidy and obscure the code. And still leaves the problem of
exactly how to deal with failures, right in the middle of some otherwise
elegant code. Especially annoying when the probability of failure is known
to be low.

I think this is the point Malcolm was making.

But there are any number of strategies for offloading the allocation
checking elsewhere, depending on too many factors to be too specific.

--
Bart

Jan 20 '08 #67
Malcolm McLean wrote:
I'd want

int user_input = get_user_input();
/* if I was sensible, sanity check here, but this is a sloppy program */
int s = user_input * sizeof(record_t);
/* at this point we've got an overflow, so compiler issues "arithmetic
overflow" and terminates. */

Unfortunately we don't get this yet. Almost no compilers will handle oveflow
nicely. However if the result is negative, which is a sporting chance, at
least we can pick it up in the call to xmalloc(). If we are in a loop
with essentially random values being typed in by user, the chance of a
negative becomes statistically certain.
OMG...
What's wrong with
if(INT_MAX / sizeof(record_t) >= user_input) {
/*do something*/
}
? Essentially you mean that the program should terminate by chance. Btw,
there is no overflow. The expression `user_input * sizeof(record_t)` has
type size_t (unless SIZE_MAX < INT_MAX...), it is reduced modulo
SIZE_MAX + 1, and it is converted to an int, and if it doesn't fit there
the result is implementation defined. And what happens if the user knows
how that works and enters numbers so that it will never cause xmalloc to
be called with a negative argument?

--
Army1987 (Replace "NOSPAM" with "email")
Jan 20 '08 #68
Eric Sosman wrote:
Malcolm McLean wrote:
>>
Typically something between 33% to 50% of code will be there to handle
malloc() failures, in constructor-like C functions.

Please cite the research that measured this surprising figure.
Probably the same one which says that more than 50% of integers are used
to index arrays?
--
Army1987 (Replace "NOSPAM" with "email")
Jan 20 '08 #69

"Army1987" <ar******@NOSPAM.itwrote in message
Malcolm McLean wrote:
>I'd want

int user_input = get_user_input();
/* if I was sensible, sanity check here, but this is a sloppy program */
int s = user_input * sizeof(record_t);
/* at this point we've got an overflow, so compiler issues "arithmetic
overflow" and terminates. */

Unfortunately we don't get this yet. Almost no compilers will handle
oveflow
nicely. However if the result is negative, which is a sporting chance, at
least we can pick it up in the call to xmalloc(). If we are in a loop
with essentially random values being typed in by user, the chance of a
negative becomes statistically certain.
OMG...
What's wrong with
if(INT_MAX / sizeof(record_t) >= user_input) {
/*do something*/
}
?
You've missed the comment. "If I was sensible I'd sanity check here". That
is to say, at the point of input.
The objection to xmalloc() is that since it takes an int rather than a
size_t, it might break in nasty way on large allocations. Which is true.
However it isn't intended for large allocations which have a realistic
chance of failing. It is meant for situations where the chance of failure is
too low for it to be worth writing custom error-handling code.

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

Jan 20 '08 #70

"Malcolm McLean" <re*******@btinternet.comwrote in message
news:7a******************************@bt.com...
>
However the literal answer to the OP's question is "when the chance of a
malloc() failure is higher than the chance of the computer breaking down,
it is worthwhile checking the return value of malloc()".
We can calculate it - it took only a few minutes with calculator to work
out that Flash's example - computer running out of memory every month, 2GB
of memory, a non-loop allocation of 20 bytes means that we are talking of
about one failure of that allocation in every ten million years of
operation. I can cope with one irate phone call every ten million years.
But it isn't always so easy to do the calculation.
I haven't tried to repeat your calculation but it somehow feels wrong.

Failing on one specific 20-byte allocation is, yes, unlikely (unlikely
enough for an appropriate wrapper, if you feel confident enough to use it,
to take the drastic step of aborting), but once in 10,000,000 years?

According to Flash it's more like once a month? And when you have many such
allocations? And when there may be thousands of copies of your software
being run daily on all sorts of machines with all sorts of unknown and
possibly dodgy software running at the same time?

You might get that phone call sooner than you think.

--
Bart
Jan 20 '08 #71
Gordon Burditt wrote:
>
.... snip ...
>
Don't bother checking the return value of malloc(0) (where the
zero value is a constant). The easist way to deal with this is
to never call malloc(0) in the first place.
It is permitted for malloc(0) to return a pointer that may not be
dereferenced. On some (probably most) malloc systems this will eat
up some memory to keep track of the size etc. of the data
allocated. This may fail, resulting in a NULL return. So you
should ALWAYS check the result of any malloc call.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 20 '08 #72
Randy Howard wrote:
CBFalconer wrote
>Randy Howard wrote:
>>CBFalconer wrote

That is more easily handled by:

void *xmalloc(size_t s) {
void *res;

if (!s) s++;

What?

Leaving s in the range 1 .. SIZE_MAX.

Yeah, but with a name like xmalloc(), you don't expect munging
of the behavior. If you called it something like
mymallocthatfixessillyrequests() maybe. I'd much rather have
it do what I ask of it, than that, and certainly not do so
quietly.
What behaviour is munged? The caller receives a pointer back. He
is not allowed to store any data there. Oh, it won't fail for 1
byte. So what. Do all systems fail for one byte overrun? The
caller never gets the modified s back. The behaviour exactly fits
the standard specification for malloc. However, you now know what
it does when called with a zero argument.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 20 '08 #73
CBFalconer <cb********@yahoo.comwrites:
Gordon Burditt wrote:
>>
... snip ...
>>
Don't bother checking the return value of malloc(0) (where the
zero value is a constant). The easist way to deal with this is
to never call malloc(0) in the first place.

It is permitted for malloc(0) to return a pointer that may not be
dereferenced. On some (probably most) malloc systems this will eat
up some memory to keep track of the size etc. of the data
allocated. This may fail, resulting in a NULL return. So you
should ALWAYS check the result of any malloc call.
I disagree. malloc(0) is the one case where one need not check the
return and checking it may even be an error! Of course, since normal
code checks the return from malloc we sometimes have to turn the check
off. Take an algorithm that works on an array and needs a work array:

double algorithm(double a, size_t n)
{
double *work_space = malloc(n * sizeof *work);
if (work_space == NULL) {
/* complain, exit, whatever... */
}
/* do stuff */
free(work_space);
return ...;
}

and I have coded it up to work even when n == 0 (it will thus not
touch any a[x] nor use work_space[x]) it will still go wrong when
called with n == 0 on some systems. I need:

if (work_space == NULL && n != 0) {
/* complain, exit, whatever... */
}

(or similar) to make it work portably. xmalloc is special case of
this and hence, Eric Sosman's suggestion. Your alternative also works
but is more wasteful.

Testing the return of malloc(0) is a bad idea because it is not
well-defined.

--
Ben.
Jan 20 '08 #74
>Don't bother checking the return value of malloc(0) (where the
>zero value is a constant). The easist way to deal with this is
to never call malloc(0) in the first place.

It is permitted for malloc(0) to return a pointer that may not be
dereferenced. On some (probably most) malloc systems this will eat
up some memory to keep track of the size etc. of the data
allocated. This may fail, resulting in a NULL return. So you
should ALWAYS check the result of any malloc call.
What's the difference between malloc(0) returning a pointer that
cannot be dereferenced (non-null) and returning a pointer that
cannot be dereferenced (null)?

Why would you ever want to call malloc(0) (argument is a constant
0, not a variable that happens to have the value zero) in the first
place? You cannot portably count on it being any different from
((void *)0), and ((void*)0) is probably faster.

Jan 20 '08 #75
On Fri, 18 Jan 2008 22:49:39 UTC, Kaz Kylheku <kk******@gmail.com>
wrote:
On Jan 18, 2:35*pm, Paul Hsieh <websn...@gmail.comwrote:
check the return because it may fail for *any* reason. *About the only
time you could possibly get away with not checking is if you have to
know an awful lot about your system and then only accept a finite
fixed amount of malloc()s right when the system starts.

Or you know that your system overcommits virtual memory, so that
malloc keeps ``working'' even though your total allocations have
already exceeded core + swap.
And then the system is set up for noswap and nocommit - and BANG!

There is nothing that forbids overcommit - but there is even nothing
that requires malloc to fail when a commit fails miserably.

malloc() is allowed to return NULL when it can not deliver memory for
a single object you needs - so check the return of c/m/realloc every
time to be sure to get memory you need and have a strategy what to do
when re/m/c/alloc tells you that it can't fullify your request.

How will malloc serve you with a memory block when overcommetted
memory gets so overcommited that still there is really no address room
left to overcommit?

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
Jan 20 '08 #76
Eric Sosman <es*****@ieee-dot-org.invalidwrites:
Malcolm McLean wrote:
>Typically something between 33% to 50% of code will be there to
handle malloc() failures, in constructor-like C functions.

Please cite the research that measured this surprising figure.
When I first read the above (insufficiently carefully), I thought
Malcolm was claiming that 33% to 50% of code *in the program* would be
there to handle malloc() failures. I think he actually meant to 33%
to 50% of the code *in a constructor-like C function*.

Given that a constructor-like function is typically going to be fairly
simple (allocate memory, initialize members, and return), 33% to 50%
doesn't seem implausible to me.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 20 '08 #77
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>It is permitted for malloc(0) to return a pointer that may not be
dereferenced. On some (probably most) malloc systems this will eat
up some memory to keep track of the size etc. of the data
allocated. This may fail, resulting in a NULL return. So you
should ALWAYS check the result of any malloc call.
And just what are you supposed to do when malloc(0) returns NULL,
since it's allowed to do that even when it succeeds?

-- Richard
--
:wq
Jan 20 '08 #78
Gordon Burditt wrote:
>
.... snip ...
>
What's the difference between malloc(0) returning a pointer that
cannot be dereferenced (non-null) and returning a pointer that
cannot be dereferenced (null)?
The null can be used as an error signal. But not if it can be
returned from a successful call. Then you also have do silly
things like protecting use of every malloced pointer with lots of
complications. For example, using my ggets input function:

while (0 == ggets(&buf)) {
if (!(temp = malloc(sizeof *temp))) {
free(buf);
break;
}
temp->data = buf; temp->next = root;
root = temp;
}
/* A complete text file has been read into memory, in lines */
/* optional */ root = reverse(root);
while (root) {
temp = root;
puts(root->data;
free(root->data)
free(root);
root = temp;
}
/* prints the whole file */

and most possible malloc failure has been handled in ggets,
aborting further data input. No special cooking of data is needed.

BTW, your message totally omitted attributions for quoted
material. Please do not do this, as it seriously harms
readability. The attributions are the initial lines of the form
"joe wrote:" which connect lines with the appropriate number of '>'
markers to joe.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 21 '08 #79
Richard Tobin wrote:
CBFalconer <cb********@maineline.netwrote:
>It is permitted for malloc(0) to return a pointer that may not be
dereferenced. On some (probably most) malloc systems this will
eat up some memory to keep track of the size etc. of the data
allocated. This may fail, resulting in a NULL return. So you
should ALWAYS check the result of any malloc call.

And just what are you supposed to do when malloc(0) returns NULL,
since it's allowed to do that even when it succeeds?
The easiest thing is to prevent it. Use a caller mechanism, such
as:

void *domalloc(size_t s) {
if (!s) s++;
return malloc(s);
}

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download section.

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

Jan 21 '08 #80
On Mon, 21 Jan 2008 15:31:11 -0600, Malcolm McLean wrote
(in article <D7******************************@bt.com>):
Given that your system runs out of memory about every month, how many times
is it likely to need hardware repairs in 25,000 months?
You've raised hand-waving to a new level of art form.
--
Randy Howard (2reply remove FOOBAR)
"The power of accurate observation is called cynicism by those
who have not got it." - George Bernard Shaw

Jan 21 '08 #81

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
Malcolm McLean said:

So whose fault is this? The customer's fault, for running the code on a
fifty-million line log file? That depends on whether the shipped code >
had a big notice on the box saying "warning - this lib was written by >
overly optimistic developers who haven't properly tested it in a real
environment".
It depends on whether the code says "returns NULL on failure" or not. If it
does then, clearly, it is lying, and it is the fault of the library vendor.

If it doesn't, customer should consider whether his machine can generate a
potentially infinite supply of them, just as he should consider whether his
arrays will fit on the stack.
When we get the irate phone call, we say "Where did it say the function will
return NULL?" "OK, your code is incorrect. Now what do you want your program
to do if it cannot allocate enough of these hash tables? Terminate with an
error message? That sounds sensible. Now what did it do?"

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

Jan 22 '08 #82
Malcolm McLean said:
>
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
>Malcolm McLean said:

So whose fault is this? The customer's fault, for running the code on a
fifty-million line log file? That depends on whether the shipped code >
had a big notice on the box saying "warning - this lib was written by >
overly optimistic developers who haven't properly tested it in a real
environment".
It depends on whether the code says "returns NULL on failure" or not. If
it does then, clearly, it is lying, and it is the fault of the library
vendor.
Granted. But the important point is this: that the allocation was for a few
lousy bytes, and yet the failure occurred very quickly - it did not take
the many thousands of hours that you were claiming it would take.

A 20 byte allocation doesn't seem like a lot, until you do it in a loop.

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

"Richard Heathfield" <rj*@see.sig.invalidwrote in message
Malcolm McLean said:

Granted. But the important point is this: that the allocation was for a >
few lousy bytes, and yet the failure occurred very quickly - it did not
take the many thousands of hours that you were claiming it would
take.

A 20 byte allocation doesn't seem like a lot, until you do it in a loop.
That's true. You used to get this problem with Midi files - it was extremely
tempting to put the notes into a linked list, but it would run a late
eighties vintage PC out of memory.
Nowadays it isn't a problem, of course, but you can still gobble a lot of
memory with big structures made of small elements.

--
Free games and programming goodies.
http://www.personal.leeds.ac.uk/~bgy1mm
Jan 22 '08 #84
"Malcolm McLean" <re*******@btinternet.comwrote:
"Richard Heathfield" <rj*@see.sig.invalidwrote in message
Granted. But the important point is this: that the allocation was for a >
few lousy bytes, and yet the failure occurred very quickly - it did not
take the many thousands of hours that you were claiming it would
take.

A 20 byte allocation doesn't seem like a lot, until you do it in a loop.
That's true. You used to get this problem with Midi files - it was extremely
tempting to put the notes into a linked list, but it would run a late
eighties vintage PC out of memory.
Nowadays it isn't a problem, of course,
Except that nowadays we're not dealing with MIDI any more, but with
MPEG-4. Parkinson' Law trumps Moore's Law.

Richard
Jan 22 '08 #85
In article <2d**********************************@k2g2000hse.g ooglegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>2. If your environment is such that any access to null pointers will
crash the program, and a crashing program is harmless:
You need to be sure that you will access the memory in a way that will
cause a crash. For example, if you allocate a 10,000 element array,
and the first element you access is the 5,000th, then you may not get
an error even if malloc() returned 0.

-- Richard

--
:wq
Jan 22 '08 #86
CBFalconer wrote:
Marty James wrote:
>>
I was reflecting recently on malloc.

Obviously, for tiny allocations like 20 bytes to strcpy a
filename or something, there's no point putting in a check on
the return value of malloc.

Oh? Try the following:

#include <stdio.h>
#include <stdlib.h>

#define SZ 40

int main(void) {
unsigned long count;
void *ptr;

count = 0;
while (ptr = malloc(SZ)) count++;
printf("Failed after %lu tries\n", count);
return 0;
}
Incidentally, on my machine (a 500 Mhz Pentium running W98 FE with
512 meg of memory) this failed after roughly 10 million tries due
to the swap file filling, in about 43 seconds. The interesting
effect is that the swap file had expanded from roughly 10 megs to
about 170 megs. After the program terminated it took several
minutes for the swap file to self (or something) empty. It only
recovered to 15 meg, however.

I have not tested it under any Linux.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.att.net>
Try the download sectioX-Mozilla-Status: 00091 20:37:25 2008
X-Mozilla-Status: 0801
X-Mozilla-Status2: 00000000
FCC: /C|/Netscape/Users/cbf/mail/sentnews
X-Mozilla-News-Host: free.teranews.com
Message-ID: <47***************@yahoo.com>
Date: Mon, 21 Jan 2008 20:37:25 -0500
From: CBFalconer <cb********@yahoo.com>
Reply-To: cb********@maineline.net
Organization: Ched Research http://cbfalconer.home.att.net
X-Mozilla-Draft-Info: internal/draft; vcard=0; receipt=0; uuencode=0; html=0; linewidth=0
X-Mailer: Mozilla 4.75 [en] (Win98; U)
X-Accept-Language: en
MIME-Version: 1.0
Newsgroups: comp.lang.c
Subject: Re: Function Pointers
References: <fd**********************************@v67g2000hse. googlegroups.com<b4******************************* ***@s12g2000prg.googlegroups.com<fn**********@aioe .org<Wc******************************@bt.com<26*** *******************************@m34g2000hsb.google groups.com<87************@kvetch.smov.org<ac****** ****************************@i7g2000prf.googlegrou ps.com<Gu******************************@bt.com<87* ***********@bsb.me.uk<G6************************** ****@bt.com>
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Richard Heathfield wrote:
Ben Bacarisse said:
.... snip ...
>>
Ditto. In fact I posted such an example in my reply to the OP!

Oops, so you did. I even read it, actually - but I have a memory
like a... like a... sort of bowl-shaped, you use it to sift, um,
well, cooky stuff, goes in bread...
You are obviously aging. The last few years I keep having problems
remembering the appropriate word (or equivalent). I know I know
it, I just can't dredge it up at the moment. It will probably come
to me later when it is of little use. I am convinced it is an age
effect, but not especially serious, since I can always refer to the
whoozit, or the watch-a-ma-call-it, etc. and anybody of any
intelligence will know exactly what I mean.

--
[mail]: Chuck F (cbfalconer at maineline dot net)
[page]: <http://cbfalconer.home.aX-Mozilla-Status: 0009ry the download section.

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

Jan 22 '08 #87
On Tue, 22 Jan 2008 17:20:13 +0000 (UTC),
dj******@csclub.uwaterloo.ca.invalid wrote:
>In article <2d**********************************@k2g2000hse.g ooglegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>>2. If your environment is such that any access to null pointers will
crash the program, and a crashing program is harmless:

I would say that a properly written wrapper that ends up calling
exit(EXIT_FAILURE) (or even abort()) on allocation failure is a better
solution in this case than letting the null pointer dereference crash
the program.
Just so. Even better is to make provision for callbacks to
handle cases where something useful can be done. Who would think
of doing such a thing.
Jan 22 '08 #88
Richard Tobin wrote:
In article <2d**********************************@k2g2000hse.g ooglegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>2. If your environment is such that any access to null pointers will
crash the program, and a crashing program is harmless:

You need to be sure that you will access the memory in a way that will
cause a crash. For example, if you allocate a 10,000 element array,
and the first element you access is the 5,000th, then you may not get
an error even if malloc() returned 0.

-- Richard
Given 'char *cp = malloc(10000);' returns 0, how would you go about
addressing 'the 5,000th' element?

--
Joe Wright
"If you think Health Care is expensive now, wait until it's free."
Jan 23 '08 #89
Joe Wright <jo********@comcast.netwrites:
Richard Tobin wrote:
>In article
<2d**********************************@k2g2000hse. googlegroups.com>,
christian.bau <ch***********@cbau.wanadoo.co.ukwrote:
>>2. If your environment is such that any access to null pointers will
crash the program, and a crashing program is harmless:

You need to be sure that you will access the memory in a way that will
cause a crash. For example, if you allocate a 10,000 element array,
and the first element you access is the 5,000th, then you may not get
an error even if malloc() returned 0.
Given 'char *cp = malloc(10000);' returns 0, how would you go about
addressing 'the 5,000th' element?
cp[4999], of course.

Naturally this invokes undefined behavior. The point is that, on some
systems, dereferencing cp itself (where cp==NULL) is likely to trap,
whereas referring to cp[4999] might not because 4999 might be a valid
address.

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 23 '08 #90
Malcolm McLean wrote:
....
However in many video games, the only possible error is "disk dirty".
How in the world did they manage to achieve that level of coding
perfection? Are the techniques they used available for scientific
programming, or do they involve some kind of black magic? Are human
sacrifices required, or is selling your soul sufficient?

Personally, I've never seen a video game without bugs, and few if any
of those bugs were traceable to dirty disks. Maybe I'm playing the
wrong kinds of games?

Jan 23 '08 #91
On Wed, 23 Jan 2008 18:57:22 -0000, "Malcolm McLean"
<re*******@btinternet.comwrote:
>The whole point of the function is to take error-handling code which will
never[1] be executed out of calling code. So if we return an error condition
we're back to square one. We might as well just call malloc().
Actually, in my opinion, it's *better* to call malloc.

--
Al Balmer
Sun City, AZ
Jan 23 '08 #92
In article <9s************@news.flash-gordon.me.uk>,
Flash Gordon <sp**@flash-gordon.me.ukwrote:
>You should, but what you do with them might be different. On some
embedded systems the correct thing to do would be enter an "infinite"
loop which will make a watchdog reset the processor. On other systems
you might want to display some appropriate error message and exit. Or
you might want to invoke some alternative code that as written by a
different team to try and solve the same problem.
Oh, I quite agree. In some cases you might even want to effectively
ignore the error (e.g. if it's just going to result in some degraded
image rendering). But there's a range of programs where abort()ing is
appropriate.

-- Richard
--
:wq
Jan 24 '08 #93
[snips]

On Wed, 23 Jan 2008 18:57:22 +0000, Malcolm McLean wrote:
The whole point of the function is to take error-handling code which
will never[1] be executed out of calling code.
If the error handling code will never be called - because malloc will
never fail - then there's simply no need for your function, the whole
point of which is to cope with situations where malloc fails.

Jan 24 '08 #94
[snips]

On Sun, 20 Jan 2008 22:48:08 +0000, Malcolm McLean wrote:
I am not in any sense tied to the xmalloc() error-handling method. If
anyone can come up with a better idea, please post. It must not return
null unless no memory is to be found, and it must be easier for caller
to use than regular malloc().
Your malloc "replacement" is not easier to use than malloc; it is, in
fact, more difficult, as it lies about what it does, then fails to even
meet the details of the lie - and it does erroneous things with perfectly
legitimate allocation requests.

So, let's see. "it must not return NULL unless no memory is to be
found". Hmm. That would be malloc.

Easier to use? You just don't *get* much easier than malloc. To call it
usefully, you have to store the result into a pointer anyhow. Validation
of success is accomplished by a single if statement: it's just about
impossible to get simpler than that and still be useful.

And if nothing else, malloc doesn't lie about what it actually does, and
works on all legitimate size requests, if memory is, in fact, available
to meet the request.

Jan 24 '08 #95
Kelsey Bjarnason wrote:
[snips]
<snip>
And if nothing else, malloc doesn't lie about what it actually does,
and works on all legitimate size requests, if memory is, in fact,
available to meet the request.
Unfortunately, only on systems that do not overcommit memory.

Jan 24 '08 #96
Malcolm wrote:
) reasonably well, but take the checks out of caller's source code, where they
) are cluttering the functions and adding to maintenance costs.

You could also argue that, in a program that always checks the return value
of malloc, most of the checks will be extremely similar. Moving often-used
pieces of code into a sub function is a Good Thing(tm).
SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
Jan 24 '08 #97

"Kelsey Bjarnason" <kb********@gmail.comwrote
On Sun, 20 Jan 2008 22:48:08 +0000, Malcolm McLean wrote:
>I am not in any sense tied to the xmalloc() error-handling method. If
anyone can come up with a better idea, please post. It must not return
null unless no memory is to be found, and it must be easier for caller
to use than regular malloc().

Your malloc "replacement" is not easier to use than malloc; it is, in
fact, more difficult, as it lies about what it does, then fails to even
meet the details of the lie - and it does erroneous things with perfectly
legitimate allocation requests.

So, let's see. "it must not return NULL unless no memory is to be
found". Hmm. That would be malloc.

Easier to use? You just don't *get* much easier than malloc. To call it
usefully, you have to store the result into a pointer anyhow. Validation
of success is accomplished by a single if statement: it's just about
impossible to get simpler than that and still be useful.
And if nothing else, malloc doesn't lie about what it actually does, and
works on all legitimate size requests, if memory is, in fact, available
to meet the request.
Sure. Once or twice in your program you may have a legitimate memory request
that could exceed the range of an int. In that case you, the programmer,
should be aware that you are asking for an enormous amount of memory. Unless
you totally control the system, you should also be aware that it is rather
likely that the request won't be honoured.

The test if(ptr == NULL) is trivial. What's non-trivial is what goes in the
if condition, You might want to put up a box for the user saying "image too
large". In which case your windowing system had better be in scope.

If the allocation is most unlikely to fail, why go through all this,
polluting things like a string duplicator with calls to windowing functions,
or stderr? In which case one version will fail if you don't compile for that
OS, whilst the other will fail under MS Windows, though not under X. Or
maybe you should litter the code with #ifdefs. That's where xmalloc() is
better.

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

Jan 24 '08 #98

"Ian Collins" <ia******@hotmail.comwrote in message
>
>Surely it's obvious that Malcolm means that these compilers don't
themselves set NDEBUG in release mode?
What is release mode? Just about every product I've worked on had it's
own set of compiler options used for production builds.
In gcc you have a -O setting to set the optimisation level. Normally you
leave it unset whilst debugging, and ramp it up to maximum for the
production build.

Microsoft compilers similarly have "debug" and "release" configurations".

In the embedded world things are different. Often you will work with a
"soft" chip which is actually an IO device attached to the PC, and only blow
a genuine device in the final stages.

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

Jan 24 '08 #99
Malcolm McLean wrote:
>
"Ian Collins" <ia******@hotmail.comwrote in message
>>
>>Surely it's obvious that Malcolm means that these compilers don't
themselves set NDEBUG in release mode?
What is release mode? Just about every product I've worked on had it's
own set of compiler options used for production builds.
In gcc you have a -O setting to set the optimisation level. Normally you
leave it unset whilst debugging, and ramp it up to maximum for the
production build.

Microsoft compilers similarly have "debug" and "release" configurations".
That's the bit I don't like, I'm sure people just select "debug" or
"release" in some IDE without evaluating all the relevant options.

--
Ian Collins.
Jan 24 '08 #100

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.