When to check the return value of malloc

R

Richard Tobin

CBFalconer said:
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
 
C

CBFalconer

pete said:
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 ...
 
C

CBFalconer

Richard said:
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.
 
P

pete

Keith Thompson wrote:
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/cvsw...c.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?
 
P

pete

CBFalconer said:
CBFalconer said:
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?
 
R

Richard Tobin

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?
[/QUOTE]
getc(arrayofstreamptrs[i++]);

Exactly; how often does that happen?

-- Richard
 
F

Flash Gordon

Peter Nilsson wrote, On 05/02/08 03:57:
[email protected] (Richard Tobin) said:
CBFalconer said:
(e-mail address removed) (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.
 
H

Herbert Rosenau

Sorry, but I disagree. Imagine any kind of tool that make a single pass over
some data, like a compiler. Imagine it runs out of memory, what should it
do? Prompting the user to free memory is out, it can't rely on even running
interactively. Yes, it could trigger an internal garbage collection, but
adding one is a significant amount of work and not even that is guaranteed
to help. Maybe it even causes OOM earlier, due to its own overhead. That's
why a compiler, given a too large sourcefile, will simply exit with an
appropriate error. It is not that it's impossible to fix the problem but
that it requires unreasonable amounts of work to do it.

No, make a clean design, define there what you can do when the amount
of data is much bigger than you may be able to handle either now or in
long run. I've written much different interpreters hunging on that
problem and found always a clean solution to get the whole work done
unattendet without the need to break the system to an state to hinder
the apps to run after my job was finished to get theyr work done
propperly.

It is easy: simply define sequence ponts you can stop the current
work, work on the data you have already aquired, if needed even
partially and restart the work thereafter on that sequence point. Such
crap as xmalloc() had the consequence of impossibility to get a
mission complete forever. There is in no way a need tto let a app fail
only because it ends in an unsuccessfull call to malloc().
That is easy, just store them in a global. Did you perhaps miss the 'to some
extent' above? If you are writing to a temporary file, you simply declare
the FILE* global and if it is non-null you clean it up with an atexit()
handler. Simple and efficient.

Oh, you are one of the peoples who are writing completely unmaintable
code? I inherented such thing from another one - ending up in an
impossible mission to get a simplr bug fixed because it was not clear
to identify which goblal was used under which condition. A rewrite of
the whole thing was needed to get that simple bug fixed without
implementing another douzend bugs instead that one.

By that avoiding the mass of globla variables there was a nice side
effect in saving memory usement by splitting some static and malloced
arrays in more flexible lists.

Productive, failsave code is up to 90% nothing than strategy to
recover from CRT and operating system errors.
Seriously, you are missing the point _COMPLETELY_. xmalloc() is not the holy
grail, it is not the remedy for any code cancer but it is a tool which
competent programmers can decide to use or not use. If it doesn't work for
your code then so be it, but nobody claimed that it should do that. It is
surely not the right tool for a multithreaded server application because
one too large client request would cause DoS for all clients. It would not
be correct to use it in a library, because there it would force the error
handling on the user of the library and thus strongly reduce its
applicability. Nobody claimed that xmalloc() was the solution there.

Oh, a library that handles errors on themself with requirering the app
to use global variables are so buggy that they are completely
unuseable and to avoid on sight.

Uh, you was saying that you have to use globals to be ready to handle
lack of memory without data loss.
C'mon, that is just bullshitting here. If you understand why globals can be
dangerous, you would also understand when they can be used without danger
and even to an advantage. Don't construct any arguments on me that I didn't
make.

True, there are are rare possibilities where globals can be really
helpfull. But these are really small exceptions.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
H

Herbert Rosenau

Now calculate the same probability for Kelsey's example.
A request for 100MB succeeds, what's the probability that a request for 100
bytes fails? (You know that the program runs on a PC, so you need to make an
assumption here, or apply some very sophisticated stats).
On the real world I've alived multiple time that som mallac(5000) were
successfull and the last malloc(25) failed miserably. Each and any
malloc() can fail regardless of each other.

Maintenance cost for a program using xmalloc() instead of a handling
that error correctly< is avoidable cost. xmalloc() can cost human
live, ruin a company.

xmalloc() in a game will loose only contended customers. It is on you
to risk your and your company reputation on your own dumbness.

--
Tschau/Bye
Herbert

Visit http://www.ecomstation.de the home of german eComStation
eComStation 1.2R Deutsch ist da!
 
D

dj3vande

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]
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.


dave
 
P

pete

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]
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++)));
}

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.
 
P

Peter Nilsson

Flash Gordon said:
Peter Nilsson wrote, On 05/02/08 03:57:
[email protected] (Richard Tobin) said:
     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.
 
F

Flash Gordon

Peter Nilsson wrote, On 06/02/08 05:33:
Flash Gordon said:
Peter Nilsson wrote, On 05/02/08 03:57:
(e-mail address removed) (Richard Tobin) wrote:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,521
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top