Can malloc ever really fail?

K

Keith Thompson

The Vax was one, IIRC. I'm afraid I'm going to be in the minority
again, but I viewed this as feature rather than flaw, since many
programs have a line like
if (foop && *foop) woo(foop);
which can now be replaced with a shorter construct.

Yes, I think you're in the minority on this one. :cool:}

I could see your point if the standard actually required this
behavior. But instead, too many programmers used the "shorter
construct", which worked just fine on the VAX, but failed mysteriously
as soon as the code was ported to another system.

Allowing null pointers to be dereferenced is not so much a convenience
as a way to postpone error detection.
 
G

Giorgos Keramidas

RoSsIaCrIiLoIA said:
Yes, excuse but when I have seen the message I have thought "what I
could do in this case?"

a=0; b=0; c=0; d=0;
if(
(a = malloc(.)) &&
(b = malloc(..)) &&
(c = malloc(...))&&
(d = malloc(....)) )
;
else {free(a); free(b); free(c); free(d);... }

FWIW, this way of writing the checks and the relevant free() calls might
call free() with a pointer that hasn't been allocated. For instance, if
the first two malloc() calls succeed but the third fails, then free(c)
is not so safe. I'd probably write this as:

a = b = c = d = NULL;
if ((a = malloc(foo)) != NULL && (b = malloc(bar)) != NULL &&
(c = malloc(baz)) != NULL && (b = malloc(foobar)) != NULL) {
if (a != NULL) free(a);
if (b != NULL) free(b);
if (c != NULL) free(c);
if (d != NULL) free(d);
return -ENOMEM;
}

/* Do stuff. */
return 0;

Giorgos
 
R

Richard Bos

Giorgos Keramidas said:
FWIW, this way of writing the checks and the relevant free() calls might
call free() with a pointer that hasn't been allocated.

Yes, but it's been set to null before the malloc() chain. Unlike normal
free() calls on non-allocated pointers, free(0) is safe - it's an
explicit requirement in the Standard.

Richard
 
R

RoSsIaCrIiLoIA

FWIW, this way of writing the checks and the relevant free() calls might
call free() with a pointer that hasn't been allocated. For instance, if
the first two malloc() calls succeed but the third fails, then free(c)
is not so safe. I'd probably write this as:

if a=malloc(.) is Ok but b=malloc(..) is not Ok then
a=0; b=0; c=0; d=0;
if( (a=malloc(.)) && /* is ok because a!=0 */
(b=malloc(..)) && /* here b==NULL==0? so go to else */
...........................
)
else { free(a); /* ok allocated*/
free(b); /* ok b==NULL==0 */
free(c); free(d); /* ok c==0 d==0 ? better free((void*) c)? */
}
where is the error?
 
G

Giorgos Keramidas

RoSsIaCrIiLoIA said:
a=0; b=0; c=0; d=0;
if( (a=malloc(.)) && /* is ok because a!=0 */
(b=malloc(..)) && /* here b==NULL==0? so go to else */
...........................
)
else { free(a); /* ok allocated*/
free(b); /* ok b==NULL==0 */
free(c); free(d); /* ok c==0 d==0 ? better free((void*) c)? */
}
where is the error?

No error, apologies. As it has been pointed out to me, I've missed a
very important part of the way free() works. Calling free(ptr) when
(ptr == NULL) is ok.
 
I

Irrwahn Grausewitz

Giorgos Keramidas said:
FWIW, this way of writing the checks and the relevant free() calls might
call free() with a pointer that hasn't been allocated.

More precisely, it may call free with a null pointer argument.
For instance, if
the first two malloc() calls succeed but the third fails, then free(c)
is not so safe.

Nope, see below.
I'd probably write this as:

a = b = c = d = NULL;
if ((a = malloc(foo)) != NULL && (b = malloc(bar)) != NULL &&
(c = malloc(baz)) != NULL && (b = malloc(foobar)) != NULL) {
if (a != NULL) free(a);
if (b != NULL) free(b);
if (c != NULL) free(c);
if (d != NULL) free(d);
<snip>

These four checks are pointless, since passing a null pointer to
free() is well defined: it results in a no-op. Having said this,
you may of course use the checks as some form of weird micro-
optimization in error handling code... ;-)

Regards
 
M

Minti

Irrwahn Grausewitz said:
More precisely, it may call free with a null pointer argument.


Nope, see below.

<snip>

These four checks are pointless, since passing a null pointer to
free() is well defined: it results in a no-op. Having said this,
you may of course use the checks as some form of weird micro-
optimization in error handling code... ;-)


What Optiminzation dude?
 
K

Keith Thompson

What Optiminzation dude?

To take a simpler example, suppose p is a pointer whose value is the
result of a call to malloc(), but we don't know whether the call was
successful or not. So p could be either a null pointer or a pointer
to a chunk of allocated memory.

The following:

free(p);

is perfectly valid, since free() allows its argument to be a null
pointer (it does nothing in this case, since there's nothing to
deallocate).

On the other hand, the following:

if (p != NULL) {
free(p);
}

is also perfectly valid. The only difference is that the latter
avoids the call to free() if p is a null pointer. If p is a null
pointer, this saves the overhead of a function call. If p is
non-null, it has the overhead of an extra comparison. Which of these
is more efficient is going to depend on several things (the overhead
of the comparison, the overhead of a function call, the probability
that p is non-null, and possibly some extremely system dependent
concerns about cache usage, branch prediction, instruction pipelining,
and whatever else I haven't thought of).

It's unlikely that the optimization is going to be significant. If it
were, the implementation would be free (sic) to define free() as a
macro that avoids the function call if the argument is a null pointer.
 

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,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top