When to check the return value of malloc

P

Phil Carmody

Keith Thompson said:
Suppose you want to sort a potentially large disk file. Whatever
algorithm you use, it's likely to involve loading chucks of the file
into memory. The more you can load, the faster the sort is likely to
be. In that particular case, it's perfectly reasonable to ask for a
large buffer and settle for a smaller one.

But that's a relatively rare special case,

It was very common in my wing of the company, I don't know about
yours. You'll find many instances of ever-shrinking DMA (thus
physically contiguous) buffer requests until one suceeds in the
various subsystem module's .probe. Ditto the various comms pipelines
like USB, WLAN, and Bluetooth even if there's no physical contiguity
requirement. It's just an instance of "graceful degradation of service",
and may apply to everything from kernels to high-level GUI apps.
and it doesn't justify
making your default memory allocator allocate a small buffer when
you ask for a large one.

Absolutely. Pretending you know what all callers want is arrogant.
Even 'falling back onto a smaller allocation' is sufficiently lacking
in detail that it might not be right even when it's right. If you want
4MB, but have a fallback that only requires 65KB, then the allocation
returning 3MB, assuming that's how much was actually available, as
earlier proposed, would be dumb.

Phil
 
K

Keith Thompson

Phil Carmody said:
Indeed - and entirely from your pen!

It's /evidence/ that is as clear as day, which, in combination with the
fact that his content is becoming more indistinguishable from a troll's,
is quite convincing; I never claimed it was /proof/. I may even be wrong.

I suggest that the fact that sandeep posts from aioe.org provides
essentially zero evidence, one way or the other, regarding whether
or not he's a troll. The evidence is entirely in the content of
his posts, which is as it should be.
 
S

Seebs

I suggest that the fact that sandeep posts from aioe.org provides
essentially zero evidence, one way or the other, regarding whether
or not he's a troll. The evidence is entirely in the content of
his posts, which is as it should be.

I think it's noticably over zero. Not a ton over zero, but some. It'd
show up in a good Bayesian filter. :)

The obvious evidence is that the moment people pointed out that he was
trolling he stopped.

-s
 
S

sandeep

Seebs said:
It overlooks nothing.

THAT IS THE SPECIFICATION OF THE LANGUAGE.


No, free won't need to read that info, because the first thing it would
do is check to see whether the pointer is a null pointer, and if it is,
return without doing anything.

It doesn't matter how easy or hard it is for the implementor to comply.
They are *REQUIRED* to correctly do nothing without crashing if a null
pointer is passed to free(). As it happens, this is very easy.

You may get away with it, but passing a NULL pointer to free is a mark of
careless code, it should never happen.

Making free check if it was passed a bad pointer is completely against
the spirit of C. There are no checks for division by 0, no checks for
array bounds - the programmer is expected and trusted to know what he is
doing. It should be the same with passing a valid pointer to free and no
good programmer should pass in a NULL pointer whether or not he will get
away with it. Forcing free to test for NULL is pointless and inefficient
if the programmer is competent.
 
K

Keith Thompson

sandeep said:
You may get away with it, but passing a NULL pointer to free is a mark of
careless code, it should never happen.

Making free check if it was passed a bad pointer is completely against
the spirit of C. There are no checks for division by 0, no checks for
array bounds - the programmer is expected and trusted to know what he is
doing. It should be the same with passing a valid pointer to free and no
good programmer should pass in a NULL pointer whether or not he will get
away with it. Forcing free to test for NULL is pointless and inefficient
if the programmer is competent.

You're wrong, but I no longer believe that there's any point in
trying to explain it to you. No matter what we tell you, however
well founded it is in the C Standard and in years of professional
experience, your recent behavior indicates that you'll just
arrogantly assert that you're right and everyone else is wrong.

If you'll change your attitude, I'd be glad to discuss it with
you further.
 
T

Tim Streater

superpollo said:
Richard Heathfield ha scritto:

excuse me: what's the difference between "can" and "may" in english? i
thought they were synonyms...

In the context where they were used here, "may" implies doubt about
getting away with it, whereas "can" implies certainty.

More generally the exact meaning will also depend on the emphasis placed
on the words when spoken.

Here's a slightly different context. If you and I are in a room
together, and I say:

"May I leave this room?"

then I'm asking permission to do so. If I say:

"Can I leave this room?"

then strictly speaking I'm asking whether it's *possible* (i.e.,
physically) for me to leave (and you may say "No" because all the doors
are locked).

Slang or everyday usage might result in these two in practice being used
interchangeably.
 
E

Eric Sosman

Seebs said:
[...]
It doesn't matter how easy or hard it is for the implementor to comply.
They are *REQUIRED* to correctly do nothing without crashing if a null
pointer is passed to free(). As it happens, this is very easy.

You may get away with it, but passing a NULL pointer to free is a mark of
careless code, it should never happen.

The ability to free(NULL) is convenient, not usually in that
exact guise but in a realloc(NULL,...) setting:

char *buff = NULL;
size_t buffsiz = 0;
...
while (something) {
...
if (len > buffsiz) {
char *temp = realloc(buff, buffsiz = len * 2);
if (temp == NULL) ...
buff = temp;
}
...
}

Without the ability to realloc(NULL,...), the buffer-growing code
would need to make a special case of the initial allocation, or
else the initial allocation would need to occur before the loop
(and the error-handling would need to be duplicated). Given that
realloc(NULL,...) is so handy, free(NULL) is pretty much a given --
"for free," as it were.
Making free check if it was passed a bad pointer is completely against
the spirit of C.

The Committee that wrote the C Standard twenty-plus years ago
paid a good deal of attention to the "spirit of C," and went so far
as to write down just what they thought the S.O.C. meant (see the
Rationale). Since they wrote the "free(NULL) is a no-op" requirement,
they plainly disagreed with your notions of the S.O.C.
There are no checks for division by 0, no checks for
array bounds - the programmer is expected and trusted to know what he is
doing.

The C Standard does not forbid either of these types of checks.
Indeed, division by zero *is* checked on *every* C implementation I've
used in the last three and a half decades.

As for "trust the programmer," yes: That's part of the S.O.C.
and the Rationale says so in exactly those words. (I consider it
unfortunate that the C1x Committee appears to be backing away from
this ideal -- but given the existence of programmers who think it a
good idea not to check for NULLs from malloc(), perhaps "trust the
programmer" is indeed no longer viable.)
It should be the same with passing a valid pointer to free and no
good programmer should pass in a NULL pointer whether or not he will get
away with it.

It's not a matter of "getting away with" anything at all. NULL
*is* a valid argument to free() and a valid first argument to realloc(),
and there's no reason for a programmer to avoid passing valid arguments.
What would you think of

int y = (x >= 0 ? x : abs(x));

.... to avoid a no-op of another kind?
Forcing free to test for NULL is pointless and inefficient
if the programmer is competent.

"Pointless" is a matter of opinion, and we can disagree about
matters of opinion. But "inefficient" has a more quantitative basis;
I'd be interested to see the measurements you've made of the penalty
free() incurs by testing whether its argument is NULL. (Suggestion:
Get hold of an open-source memory management library, maybe glibc,
and build versions with and without the NULL test in free(). Run a
suite of actual programs with both library versions, and measure the
speed difference. Discuss.)

Finally, there's your "if the programmer is competent" line.
I put it to you that a programmer who fails to check the value of
malloc(), realloc(), or calloc() against NULL is not competent,
not competent enough to write C at any rate.
 
S

Seebs

You may get away with it, but passing a NULL pointer to free is a mark of
careless code, it should never happen.

Why not? It's a value returned by malloc(). :)
Making free check if it was passed a bad pointer is completely against
the spirit of C. There are no checks for division by 0, no checks for
array bounds - the programmer is expected and trusted to know what he is
doing. It should be the same with passing a valid pointer to free and no
good programmer should pass in a NULL pointer whether or not he will get
away with it. Forcing free to test for NULL is pointless and inefficient
if the programmer is competent.

Do some maintenance programming for a few years and get back to us on that,
'k?

-s
 
S

Seebs

Richard Heathfield ha scritto:
excuse me: what's the difference between "can" and "may" in english? i
thought they were synonyms...

No, they both have several different meanings.

The relevant ones are: "may" => "it is possible", "can" => "it is certain".
I *may* be able to fix this bug today, I *can* have a look at it right after
lunch. I *may* get away with code that tries to dereference a null pointer,
I *can* get away with code that takes the address of a valid object, converts
it to a pointer to unsigned char, and reads the first byte of that object
through that pointer.

The other distinction they sometimes have, in a different context, is that
"can" denotes capability, while "may" denotes permission. I *can* drive
well over the speed limit. I *may* drive slightly under the speed limit.

So "may" denotes either permission (in some contexts) or possibility which
is uncertain (in others). "can" denotes definite capability.

-s
 
S

Seebs

Richard Heathfield ha scritto:
as opposed to -- say -- dereferencing NULL?

Right. It is explicitly defined that free(NULL) *MUST NOT* do anything.
In particular, it must not introduce undefined behavior. (On a system where
dereferencing a null pointer is safe, of course, the library is welcome to
do so...)

-s
 
S

Seebs

The word "may" can also denote something hypothetical, which I suspect
is how sandeep meant it:
"Well, two plus two may be equal to four, but I don't have to like it!"

Ah-hah!

I had interpreted it as a possibility-may, but it also makes sense as a
hypothetical-may.

-s
 
E

Eric Sosman

[...]
I put it to you that a programmer who fails to check the value of
malloc(), realloc(), or calloc() against NULL is not competent,
not competent enough to write C at any rate.

"Upon further review," as they say in American football, I'll
back down just a little bit on this. I've seen an instance where
an unchecked realloc() was all right, because (1) the new size was
strictly smaller than the old and (2) the code was part of "the
implementation," and could therefore rely on implementation-specific
knowledge like "A shrinking realloc() always succeeds" (the C library
does not guarantee this, but an implementor privy to the details of
a particular implementation might know it anyhow).

HOWEVER, the reason I was looking at the code was that a crash
bug had been reported. Not far from the un-checked realloc() I
found (paraphrased)

/* Free the strings and the NULL-terminated array of
* pointers to them. Each string was obtained from malloc()
* and friends, as was the array of pointers.
*/
void discard(char **array) {
while (*array!= NULL)
free (*array++);
free (array);
}

So even though the un-checked realloc() *might* have been valid,
it turns out that the programmer was a blunderer all the same.
 
K

Keith Thompson

Seebs said:
No, they both have several different meanings.

The relevant ones are: "may" => "it is possible", "can" => "it is certain".
I *may* be able to fix this bug today, I *can* have a look at it right after
lunch. I *may* get away with code that tries to dereference a null pointer,
I *can* get away with code that takes the address of a valid object, converts
it to a pointer to unsigned char, and reads the first byte of that object
through that pointer.

The other distinction they sometimes have, in a different context, is that
"can" denotes capability, while "may" denotes permission. I *can* drive
well over the speed limit. I *may* drive slightly under the speed limit.

So "may" denotes either permission (in some contexts) or possibility which
is uncertain (in others). "can" denotes definite capability.

The word "may" can also denote something hypothetical, which I suspect
is how sandeep meant it:

"Well, two plus two may be equal to four, but I don't have to like it!"

There's no implication there of any real possibility that 2+2!=4.

English is not always entirely consistent.
 
K

Keith Thompson

superpollo said:
Richard Heathfield ha scritto: [...]
"You may get away with it" strongly suggests "might" rather than "can",
but the language standard *requires* that the implementation behaves
properly on free(NULL). In this case, "behaves properly" means "doesn't
do anything to affect the notional state of the abstract machine" - i.e.
free(NULL) is basically a nop.

as opposed to -- say -- dereferencing NULL?

Yes. free(NULL) is required to do nothing. Deferencing a null pointer
invokes undefined behavior.
 
L

lawrence.jones

Seebs said:
Speaking of GNU C: Nested functions, worst idea ever.

But an old one. Back in the pre-ANSI days, Pennello and DeRemer's
MetaWare C compiler (which was written in Pascal[!]) supported nested
functions.
 
S

sandeep

Eric said:
The ability to free(NULL) is convenient, not usually in that
exact guise but in a realloc(NULL,...) setting:

I think you have a serious misunderstanding here. realloc does not always
call free, for example if it is passed a smaller size to reallocate. It
is nice to be able to pass NULL to realloc to get extra functionality,
with free there is no new functionality from passing NULL.
Given that
realloc(NULL,...) is so handy, free(NULL) is pretty much a given -- "for
free," as it were.

I don't see why at all.
The C Standard does not forbid either of these types of checks.
Indeed, division by zero *is* checked on *every* C implementation I've
used in the last three and a half decades.

You may not have used many implementations then. Maybe the division is
getting optimized out - try volatile. For example on gcc

main()
{
volatile a=0;
a=1/a;
}

Running this on Linux produces,
Floating point exception
It's not a matter of "getting away with" anything at all. NULL
*is* a valid argument to free() and a valid first argument to realloc(),
and there's no reason for a programmer to avoid passing valid arguments.
What would you think of

int y = (x >= 0 ? x : abs(x));

... to avoid a no-op of another kind?

What would you think of passing a NULL pointer to strlen or fclose? Even
if you can get away with it in the case of free, it is sloppy programming.
 
K

Keith Thompson

sandeep said:
Eric Sosman writes: [...]
The C Standard does not forbid either of these types of checks.
Indeed, division by zero *is* checked on *every* C implementation I've
used in the last three and a half decades.

You may not have used many implementations then. Maybe the division is
getting optimized out - try volatile. For example on gcc

main()
{
volatile a=0;
a=1/a;
}

Running this on Linux produces,
Floating point exception

Right. The floating point exception is the result of the check.
What did you expect?

[...]
What would you think of passing a NULL pointer to strlen or fclose?

Undefined behavior, unlike free(NULL).
Even
if you can get away with it in the case of free, it is sloppy programming.

Suppose we have a pointer object that we know we're not going to
be using anymore. Depending on what's happened previously, either
it's null or it points to an allocated object. For example, say
it's in an interactive program, where a certain command requires
the creation and use of a buffer. If the user doesn't invoke that
command, the buffer is never allocated, but if the user invokes
the command multiple times, the same buffer is re-used. Now we're
leaving the mode in which that command is available, and we want
to deallocate the buffer if it was allocated. Assume that that's
the only cleanup that's necessary.

Is it ok with you if I write this?

free(buf);

or must I write this?

if (buf != NULL) {
free(buf);
}
 
W

Walter Banks

Seebs said:
Speaking of GNU C: Nested functions, worst idea ever.

Done right, used right nested functions can be very useful.
I have done a lot of programming in Pascal and controlling
function scope in a application offers some real advantages.

I have probably started a flame war on this. C has variable
scoping sorted out but does not have similar capabilities of
function scoping. At a WG-14 meeting I once brought up
nested functions. Most the arguments against were
conventional implementations related.

To be clear it will never happen as part of the standard
but I like the ability to declare a function with a function
to process some small local function that gets used multiple
times.

Regards,


Walter..
 
B

Ben Pfaff

Seebs said:
Speaking of GNU C: Nested functions, worst idea ever. I have never seen
them used in a remotely sane way. I did, however, just encounter a provably
insane nested function which Made No Sense At All. Also it caused crashes
on the ARM compiler. But mostly it was just insane.

The handy property of nested functions is that they can use the
automatic variables of the function in which they are nested.
This can be much more convenient than packaging them up inside a
struct or passing them as potentially numerous arguments to a
function.

Obviously nested functions can be misused to obfuscate. But
carefully used they can clarify code.

But there's not much point in talking about them in a C context,
since they can't be used in portable code anyhow.
 
N

Nisse Engström

In the UK, at a STOP sign (black text in red triangle on white
background), you are *required* to use your hand-brake, since you must
bring the vehicle to a complete and safe stop. (But of course you don't
use it /instead/ of the regular brakes - you use the footbrake to stop
the car, and then the handbrake to keep it stopped.)

Are you sure about this? I don't recall reading anything
about the hand-brake and Stop signs in the Highway Code,
but then, my copy is several years old and currently
mislocated. Fortunately, it is available on the web these
days:

<http://www.direct.gov.uk/en/TravelAndTransport/Highwaycode/DG_070332>

I can't find anything about hand-brakes in relation to
diagram 601.1 in the TSRGD either, but I have only performed
the most cursorest of readings so I might not even be looking
at the right document.

<http://www.opsi.gov.uk/si/si2002/20023113.htm#16>
<http://www.opsi.gov.uk/si/si2002/02311331.gif>

[Unusual shades of triangular has been mentioned elsewhere.]


/Nisse
 

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,770
Messages
2,569,588
Members
45,093
Latest member
Vinaykumarnevatia00

Latest Threads

Top