468,490 Members | 2,645 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 6932
pete wrote:
>
Are you sure getc isn't a macro on your Sun cc?
Bugger, I forgot the 'f'....

--
Ian Collins.
Feb 3 '08 #151
In article <60**************@mid.individual.net>,
Ian Collins <ia******@hotmail.comwrote:
>Just because it's a quiet Sunday afternoon, I just tried compiling this
with Sun cc:

#include <stdio.h>

int main() {
int n = getc( stdin );
}

The preprocessor output is:

int main()
{
int n =
(--((&__iob[0]))->_cnt<0?__filbuf((&__iob[0])):(int)*((&__iob[0]))->_ptr++);
}

Due to cc "knowing" and therefore being able to inline standard library
functions. I guess other compilers can do the same.
This is just because getc() is a macro. If it was an inline function,
you wouldn't see anything special in the preprocessor output. stdin is
probably also a macro expanding to &__iob[0].

-- Richard
--
:wq
Feb 3 '08 #152
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>Keith Thompson wrote:
>The buffer behavior of getc should normally be identical to the buffer
behavior of fgetc.
>Not so. The typical action of a getc macro will be something like:
[...]
>totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.
Here's the fgetc code from a real implementation:
--------
int
fgetc(FILE *fp)
{
return (__sgetc(fp));
}
--------
(<http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fgetc.c?rev=1.5&content-type=text/x-cvsweb-markup>)

Compare that with the macro definition of getc from the same
implementation:
--------
#define getc(fp) __sgetc(fp)
--------
(<http://www.openbsd.org/cgi-bin/cvsweb/src/include/stdio.h?rev=1.35&content-type=text/x-cvsweb-markup>, almost at the bottom)

Where are all those intermediate system calls? I think reality
disagrees with you here.
dave

--
Dave Vandervies dj3vande at eskimo dot com
This means we could concievably replace all our coal plants with equivalent
nuclear plants, have a Chernobyl-scale incident every six years, and be
better off. --Shalon Wood in the scary devil monastery
Feb 3 '08 #153
Ian Collins wrote:
Flash Gordon wrote:
>>
I would normally use getc rather than fgetc just in case it is
more efficient (also it is one less character to type), but with
modern systems I would not actually expect any major difference.

Just because it's a quiet Sunday afternoon, I just tried
compiling this with Sun cc:
Its nowhere near Sunday afternoon here :-)
>
#include <stdio.h>

int main() {
int n = getc( stdin );
}

The preprocessor output is:

int main()
{
int n =
(--((&__iob[0]))->_cnt<0?__filbuf((&__iob[0])):(int)*((&__iob[0]))->_ptr++);
}

Due to cc "knowing" and therefore being able to inline standard
library functions. I guess other compilers can do the same.
That macro is only usable on your particular installation. Here is
the gen:

7.19.7.5 The getc function

Synopsis
[#1]
#include <stdio.h>
int getc(FILE *stream);

Description

[#2] The getc function is equivalent to fgetc, except that
if it is implemented as a macro, it may evaluate stream more
than once, so the argument should never be an expression
with side effects.

Returns

[#3] The getc function returns the next character from the
input stream pointed to by stream. If the stream is at end-
of-file, the end-of-file indicator for the stream is set and
getc returns EOF. If a read error occurs, the error
indicator for the stream is set and getc returns EOF.

--
[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

Feb 3 '08 #154
dj******@csclub.uwaterloo.ca.invalid wrote:
CBFalconer <cb********@maineline.netwrote:
>Keith Thompson wrote:
>>The buffer behavior of getc should normally be identical to the
buffer behavior of fgetc.
>Not so. The typical action of a getc macro will be something like:

[...]
>totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.

Here's the fgetc code from a real implementation:
.... snip ...
Where are all those intermediate system calls? I think reality
disagrees with you here.
Nothing forces any implementation to supply such a macro. The
better systems do, if possible.

--
[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

Feb 3 '08 #155
CBFalconer wrote:
Ian Collins wrote:
>Flash Gordon wrote:
>>I would normally use getc rather than fgetc just in case it is
more efficient (also it is one less character to type), but with
modern systems I would not actually expect any major difference.
Just because it's a quiet Sunday afternoon, I just tried
compiling this with Sun cc:

Its nowhere near Sunday afternoon here :-)
We're way ahead of the pack down here!
>
That macro is only usable on your particular installation.
I know, the post was total bollocks, if I could have deleted it I would.
I should stick to sitting in the sun on Sundays...

--
Ian Collins.
Feb 3 '08 #156
CBFalconer wrote:
>
Nothing forces any implementation to supply such a macro. The
better systems do, if possible.
I guess with C99, it (along with other trivial standard library
functions) could have been an inline function.

--
Ian Collins.
Feb 3 '08 #157
CBFalconer <cb********@yahoo.comwrites:
Keith Thompson wrote:
[...]
>The buffer behavior of getc should normally be identical to the buffer
behavior of fgetc. The only likely difference is the overhead of a
single function call for fgetc. If getc performs a system call to
refill the buffer every 1000 times, then fgetc performs a system call
to refill the buffer every 1000 times. (It's not clear whether their
behavior with respect to refilling the buffer is required to be
identical, but there's no reason for them to be different.)

Not so. The typical action of a getc macro will be something like:

#define getc(f) do { \
if (f->ix <= f->sz) return f->buf[f->ix++]; \
else return _getnew(f); \
} while (0)

totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance. Of course there need not be any getc macro available
either.
The details of your macro definition are a bit off (it won't have a
return statement, and a do-while statement can't appear in an
expression), but I get the idea. If there are any characters
remaining in the buffer, it simply returns the next one. If the
buffer is empty, it first fills it by performing a function call. If
the buffer is N bytes, then only 1 out of every N calls will require a
system call.

What makes you think that fgetc() won't do *exactly* the same thing?
Again, the only difference is the overhead of a single function call
(not a system call) for fgetc().

--
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"
Feb 3 '08 #158
CBFalconer wrote:
>
dj******@csclub.uwaterloo.ca.invalid wrote:
CBFalconer <cb********@maineline.netwrote:
Keith Thompson wrote:
>The buffer behavior of getc should normally be identical to the
buffer behavior of fgetc.
Not so. The typical action of a getc macro will be something like:
[...]
totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.
Here's the fgetc code from a real implementation:
... snip ...
Where are all those intermediate system calls? I think reality
disagrees with you here.

Nothing forces any implementation to supply such a macro. The
better systems do, if possible.
The point that you are making,
in the case that when a getc macro is supplied:
that the getc function uses a system call and
that the getc macro doesn't,
is unfounded.

In cases when the getc macro is supplied,
then the getc function most likely
is nothing more than a wrapper
for either the getc macro or an equivalent macro.

--
pete
Feb 3 '08 #159
pete wrote:
>
CBFalconer wrote:

dj******@csclub.uwaterloo.ca.invalid wrote:
CBFalconer <cb********@maineline.netwrote:
>Keith Thompson wrote:
>
>>The buffer behavior of getc should normally be identical to the
>>buffer behavior of fgetc.
>
>Not so. The typical action of a getc macro will be something like:
>
[...]
>
>totally avoiding all system calls until the buffer is emptied.
>It's those intermediate system calls that can eat up the
>performance.
>
Here's the fgetc code from a real implementation:
>
... snip ...
Where are all those intermediate system calls? I think reality
disagrees with you here.
Nothing forces any implementation to supply such a macro. The
better systems do, if possible.

The point that you are making,
in the case that when a getc macro is supplied:
that the getc function uses a system call and
that the getc macro doesn't,
is unfounded.
But I see that's not the point you're making.

The point that you are making,
in the case that when a getc macro is supplied:
that the fgetc function uses a system call and
that the getc macro doesn't,
is unfounded.

In cases when the getc macro is supplied,
then the fgetc function most likely
is nothing more than a wrapper
for either the getc macro or an equivalent macro.

--
pete
Feb 3 '08 #160
Keith Thompson wrote:
>
.... snip ..
>
What makes you think that fgetc() won't do *exactly* the same
thing? Again, the only difference is the overhead of a single
function call (not a system call) for fgetc().
That's going to be highly system dependent. The way to get the
most available performance is to use the getc macro if available
and suitable. Suitable has to do with the multiple evaluation of
parameters.

--
[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

Feb 4 '08 #161
pete wrote:
CBFalconer wrote:
>dj******@csclub.uwaterloo.ca.invalid wrote:
>>CBFalconer <cb********@maineline.netwrote:
Keith Thompson wrote:

The buffer behavior of getc should normally be identical to
the buffer behavior of fgetc.

Not so. The typical action of a getc macro will be something
like:

[...]

totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.

Here's the fgetc code from a real implementation:
... snip ...
>>Where are all those intermediate system calls? I think reality
disagrees with you here.

Nothing forces any implementation to supply such a macro. The
better systems do, if possible.

The point that you are making,
in the case that when a getc macro is supplied:
that the getc function uses a system call and
that the getc macro doesn't,
is unfounded.

In cases when the getc macro is supplied, then the getc function
most likely is nothing more than a wrapper for either the getc
macro or an equivalent macro.
Not so. Note the provisions for multiple evaluation of the getc
parameter. Thus the macro may not be usable for some calls,
requiring the use of:

whatever = (getc)(f);

which avoids calling the macro.

--
[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

Feb 4 '08 #162
CBFalconer wrote:
>
pete wrote:
In cases when the getc macro is supplied, then the getc function
most likely is nothing more than a wrapper for either the getc
macro or an equivalent macro.

Not so. Note the provisions for multiple evaluation of the getc
parameter. Thus the macro may not be usable for some calls,
requiring the use of:

whatever = (getc)(f);

which avoids calling the macro.
You're missing a point.
The multiple evaluation of an argument by a macro,
only makes a difference when the evaluation of
the argument has side effects.

Concerning the getc function,
the evaluation of the argument in a function call
will have side effects,
but the evaluation of the parameter object inside
of the function will not have side effects,
it's just a simple pointer object.
If the wrapper function then calls the macro,
then it won't matter if the macro evaluates
the argument 5 zillion times,
the side effects will only occur once.

The point is simpler to illustrate with putc than getc:

/* BEGIN new.c output */

The putc macro output, with 'X' as the int argument
when the stream argument outputs '0' as a side effect:00X

The putc_wrapper output, with 'X' as the int argument
when the stream argument outputs '0' as a side effect:0X

/* BEGIN new.c output */

/* BEGIN new.c */

#include<stdio.h>

int putc_wrapper(int c, FILE *stream)
{
return putc(c, stream);
}

int main(void)
{

#ifndef putc
puts("putc isn't a macro here and now.");
#else
puts("/* BEGIN new.c output */\n");
printf("The putc macro output, with 'X' as the int argument\n"
"when the stream argument outputs '0' as a side effect:");
putc ('X', (printf("0"), stdout));
puts("\n");
printf("The putc_wrapper output, with 'X' as the int argument\n"
"when the stream argument outputs '0' as a side effect:");
putc_wrapper('X', (printf("0"), stdout));
puts("\n\n/* BEGIN new.c output */");
#endif

return 0;
}

/* END new.c */

--
pete
Feb 4 '08 #163
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>That's going to be highly system dependent. The way to get the
most available performance is to use the getc macro if available
and suitable. Suitable has to do with the multiple evaluation of
parameters.
It's *very* rare for multiple evaulation of the getc() parameter to
be a problem. How often does the selection of a stream have side
effects?

-- Richard
--
:wq
Feb 4 '08 #164
pete wrote:
CBFalconer wrote:
pete wrote:
>>In cases when the getc macro is supplied, then the getc function
most likely is nothing more than a wrapper for either the getc
macro or an equivalent macro.

Not so. Note the provisions for multiple evaluation of the getc
parameter. Thus the macro may not be usable for some calls,
requiring the use of:

whatever = (getc)(f);

which avoids calling the macro.

You're missing a point.
The multiple evaluation of an argument by a macro, only makes a
difference when the evaluation of the argument has side effects.
True.

.... snip ridiculous erroneous mixed-up monstrosity ...

--
[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

Feb 4 '08 #165
Richard Tobin wrote:
CBFalconer <cb********@maineline.netwrote:
>That's going to be highly system dependent. The way to get the
most available performance is to use the getc macro if available
and suitable. Suitable has to do with the multiple evaluation of
parameters.

It's *very* rare for multiple evaulation of the getc() parameter to
be a problem. How often does the selection of a stream have side
effects?
getc(arrayofstreamptrs[i++]);

for example.

--
[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

Feb 4 '08 #166
dj******@csclub.uwaterloo.ca.invalid wrote:
>
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
Keith Thompson wrote:
The buffer behavior of getc
should normally be identical to the buffer
behavior of fgetc.
Not so. The typical action of a getc macro will be something like:

[...]
totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.

Here's the fgetc code from a real implementation:
--------
int
fgetc(FILE *fp)
{
return (__sgetc(fp));
}
--------
(<http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdio/fgetc.c?rev=1.5&content-type=text/x-cvsweb-markup>)

Compare that with the macro definition of getc from the same
implementation:
--------
#define getc(fp) __sgetc(fp)
--------
(<http://www.openbsd.org/cgi-bin/cvsweb/src/include/stdio.h?rev=1.35&content-type=text/x-cvsweb-markup>, almost at the bottom)

Where are all those intermediate system calls? I think reality
disagrees with you here.
Is __sgetc also a macro?

--
pete
Feb 4 '08 #167
CBFalconer wrote:
>
dj******@csclub.uwaterloo.ca.invalid wrote:
CBFalconer <cb********@maineline.netwrote:
Keith Thompson wrote:
>The buffer behavior of getc should normally be identical to the
buffer behavior of fgetc.
Not so. The typical action of a getc macro will be something like:
[...]
totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.
Here's the fgetc code from a real implementation:
... snip ...
Where are all those intermediate system calls? I think reality
disagrees with you here.

Nothing forces any implementation to supply such a macro. The
better systems do, if possible.
What is your reason for believing that fgetc makes system calls?

--
pete
Feb 5 '08 #168
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
>It's *very* rare for multiple evaulation of the getc() parameter to
be a problem. How often does the selection of a stream have side
effects?
getc(arrayofstreamptrs[i++]);
Exactly; how often does that happen?

-- Richard
--
:wq
Feb 5 '08 #169
rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
CBFalconer *<cbfalco...@maineline.netwrote:
rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
It's *very* rare for multiple evaulation of the
getc() parameter to be a problem. *How often
does the selection of a stream have side effects?
* * *getc(arrayofstreamptrs[i++]);

Exactly; how often does that happen?
Probably less often than getc(f = param->fp).

--
Peter
Feb 5 '08 #170
Peter Nilsson wrote, On 05/02/08 03:57:
rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
>CBFalconer <cbfalco...@maineline.netwrote:
>>rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
It's *very* rare for multiple evaulation of the
getc() parameter to be a problem. How often
does the selection of a stream have side effects?
getc(arrayofstreamptrs[i++]);
Exactly; how often does that happen?

Probably less often than getc(f = param->fp).
Where it does not matter if about the side-effect occurring multiple
times and the compiler is likely to optimise it down to one occurrence.
Although I have to say that I would be more likely to write the above as
two separate statements.
--
Flash Gordon
Feb 5 '08 #171
dj******@csclub.uwaterloo.ca.invalid wrote:
>
In article <47***********@mindspring.com>,
pete <pf*****@mindspring.comwrote:
dj******@csclub.uwaterloo.ca.invalid wrote:
>
In article <47***************@yahoo.com>,
CBFalconer <cb********@maineline.netwrote:
Keith Thompson wrote:

The buffer behavior of getc
should normally be identical to the buffer
behavior of fgetc.

Not so.
The typical action of a getc macro will be something like:

[...]

totally avoiding all system calls until the buffer is emptied.
It's those intermediate system calls that can eat up the
performance.

[snip OpenBSD fgetc and getc code]
Where are all those intermediate system calls? I think reality
disagrees with you here.
Is __sgetc also a macro?

Yes:
--------
#define __sgetc(p) (--(p)->_r < 0 ? __srget(p) : (int)(*(p)->_p++))
--------
__srget is NOT a macro, and it appears to accomplish "fill the buffer
and return the next character".

So if we expand that macro we get:
--------
#define getc(fp) (--(fp)->_r < 0 ? __srget(fp) : (int)(*(fp)->_p++))
--------
int
fgetc(FILE *fp)
{
return ((--(fp)->_r < 0 ? __srget(fp) : (int)(*(fp)->_p++)));
}
--------
as what the compiler actually sees, and it still has fgetc doing
exactly the same thing as getc except wrapped up in a function.
That's what I expected.
Thank you.

I would also expect the body of the getc function definition
to be identical to the body of the fgetc function definition
in any C implementation,
regardless of whether or not getc was also defined as a macro.

--
pete
Feb 6 '08 #172
Flash Gordon <s...@flash-gordon.me.ukwrote:
Peter Nilsson wrote, On 05/02/08 03:57:
rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
CBFalconer *<cbfalco...@maineline.netwrote:
* * *getc(arrayofstreamptrs[i++]);
>
... how often does that happen?
Probably less often than getc(f = param->fp).

Where it does not matter if about the side-effect
occurring multiple times
Chapter and verse please.
and the compiler is likely to optimise it down to
one occurrence.
Irrelevant. The same could be said for...

unsigned ui;
(ui = 42) | (ui = 42);

Whatever the obvious expected result, the code invokes
undefined behaviour.

--
Peter
Feb 6 '08 #173
Peter Nilsson wrote, On 06/02/08 05:33:
Flash Gordon <s...@flash-gordon.me.ukwrote:
>Peter Nilsson wrote, On 05/02/08 03:57:
>>rich...@cogsci.ed.ac.uk (Richard Tobin) wrote:
CBFalconer <cbfalco...@maineline.netwrote:
getc(arrayofstreamptrs[i++]);
... how often does that happen?
Probably less often than getc(f = param->fp).
Where it does not matter if about the side-effect
occurring multiple times

Chapter and verse please.
>and the compiler is likely to optimise it down to
one occurrence.

Irrelevant. The same could be said for...

unsigned ui;
(ui = 42) | (ui = 42);

Whatever the obvious expected result, the code invokes
undefined behaviour.
Oops, I missed that. However, my suggestion of using
f = param->fp;
getc(f)
still applies. I can see no good reason not to have done this.
--
Flash Gordon
Feb 7 '08 #174

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.