Can malloc ever really fail?

C

Chess Saurus

I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

-Chess
 
C

Christopher Benson-Manica

Chess Saurus said:
I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

Why not read a few threads down for a lovely discussion of this very
topic? (Yes, it can fail.)
 
D

Dan Pop

In said:
I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {

I hope you don't write it like this in your real code! You certainly
don't want to assing 0 or 1 to variable a.
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

Do you have a contract with God (or Satan or whatever) that your
programs will NEVER be executed on a system running out of virtual
memory?

If appropriate to your application, you can do the following:

void *xmalloc(size_t size)
{
void *p = malloc(size);
if (p == NULL) {
/* error code */
exit(EXIT_FAILURE); /* or abort(); */
}
return p;
}

and use xmalloc instead of malloc, without ever checking its return
value.

Dan
 
W

William Ahern

Chess Saurus said:
I'm getting a little bit tired of writing

Then don't use C. Or alternatively some people write an xmalloc() wrapper
which does something like:

void *xmalloc(size_t len) {
void *p = malloc(len);

if (p == NULL)
exit(EXIT_FAILURE);

return p;
}

Of course, don't forget to put a big fat disclaimer on your code/application
which says: Don't under any circumstances depend on this program for
anything other than your own amusement.
 
B

Ben Pfaff

I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {
// error code
}

That doesn't even work. How can you be tired of writing it if
you don't even know how to write it correctly? ;-)
 
G

Gordon Burditt

I'm getting a little bit tired of writing
if (a = malloc(...) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

The *PROGRAM* can run out of virtual memory well before the *SYSTEM*
runs out of virtual memory. Sometimes particular programs (or
mortal users in general) are limited because having the whole system
come down due to the actions of one memory hog is undesirable.
This feature is sometimes called 'ulimit' (after the shell command
that sets the limits).

One real, practical example: the Exim mail transfer agent tends
(at least it did a couple of years ago when I identified this
problem) to leak a little bit of memory (something around the size
of the message headers, e.g. 2k bytes) each time it rejects a message
for syntax errors in headers. This memory is recovered when the
particular SMTP conversation terminates and the process exits (which
typically happens in less than a minute). Doesn't sound like a big
problem, right, especially for a machine with 500MB of RAM and 1GB
of swap, does it?

Now enter a spammer who establishes a connection ONCE, and sends a
quarter million spams (all rejected, and no, I did not make this
number up, I counted log entries) down that one connection over a
period of a couple of days. Now the process has leaked 500MB, the
system is swapping a lot, and since this isn't the only process
receiving junk from the same spammer, it runs out of swap space,
after having slowed down to a crawl with heavy swapping. In this
case, setting the ulimit low enough to abort the connection after
it had received an unreasonable number of messages prevented this
spammer from killing service for other people actually sending
useful mail. One process would die, the spammer would get dumped
and start up another connection, and continue getting spams rejected.
The rest of the system was relatively unaffected.

Of course, the real fix is to remove the leak, but I didn't know
enough about the internals of the code to do that.

Gordon L. Burditt
 
M

Malcolm

Chess Saurus said:
I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?
It's a theoretical problem much more than a practical problem, on most
systems. No computer can provide infinite memory space. However, as we
discussed elsethread, if you are allocating 100 bytes on a 10MB machine, and
the computer runs out of memory every ten minutes, it will be about two
years before your allocation is the one to get hit, and your error-handling
code executes. Since desktop computers probably break down every two years
or so due to compenent failure, this isn't something to get too worked up
about.

The worst problem is when you use memory internally. Consider this function

/*
check if two points on a maze are connected.
*/
bool connected(const char *maze, int width, int height, int x1, int y1, int
x2, int y2)

The problem is, you will probably write the function using a recurive
floodfill to a temporary buffer, which you have to allocate. So you have to
change the interface to return an out of memory condition, which is messy.
The problem is particularly acute if you design functions top down, and only
realise late on that one function near the bottom needs to allocate some
memory, and then the error has to be propagated up through several
redesigned layers.

Fortunately, most functions which allocate memory will return it, so you can
simply return a NULL pointer to indicate out of memory.

Usually when you are calling malloc() you don't know at compile time how
many bytes you will need, and you always have to be alert for abuse. For
instance a legitimate filename will be under a kilobyte, but a hacker could
pass a name several megabytes long to see if he can exploit the system. So
just ignoring the return isn't a good option.
 
C

Christian Bau

"Malcolm said:
It's a theoretical problem much more than a practical problem, on most
systems. No computer can provide infinite memory space. However, as we
discussed elsethread, if you are allocating 100 bytes on a 10MB machine, and
the computer runs out of memory every ten minutes, it will be about two
years before your allocation is the one to get hit, and your error-handling
code executes. Since desktop computers probably break down every two years
or so due to compenent failure, this isn't something to get too worked up
about.

If you have a program with 100,000 bugs, which crashes every ten
minutes, it will be about two years before your bug is the one that gets
hit, so there is no point in fixing any bugs, right? Something somewhere
is wrong with that logic...
 
K

Keith Thompson

Malcolm said:
It's a theoretical problem much more than a practical problem, on most
systems. No computer can provide infinite memory space. However, as we
discussed elsethread, if you are allocating 100 bytes on a 10MB machine, and
the computer runs out of memory every ten minutes, it will be about two
years before your allocation is the one to get hit, and your error-handling
code executes. Since desktop computers probably break down every two years
or so due to compenent failure, this isn't something to get too worked up
about.

Malcolm's point of view is not universally held. Rather than re-hash
the argument, I refer interested readers to the "If malloc fails"
thread.
 
M

Minti

I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

Two solutions come to my mind.

1:

a = malloc(.);
b = malloc(..);
c = malloc(...);
d = malloc(....);
// Don't use either a....d until you perform the test below.
if ( ! ( a && b && c && d ) )
{
// Deal with error;
}
2:


e = malloc( .......... );
if ( ! e ) { /* Deal with error */ }
a[0] = e;
a[1] = e + a_req;
b[0] = a[1] ;
b[1] = b[0] + b_req;
........



Then use a[0] ... d[0] for manipulation.

N.B. The second solution can be improved. Possibly by using
structures. I haven't used it ever. I am just lazy.
 
M

Mabden

Chess Saurus said:
I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

When I worked at a DotCom that ran Windows webcams online, we would make a
noise whenever someone logged into your webcam and another one when people
left. Popular sites (usually girls online) would trigger the noise many many
times a day.
The problem was that MS had a bug (leak) in their audio routines that
allocated a small chunk of memory everytime you called it. Since the webcam
software ran for days at a time, the 16bits or so added up and caused
programs to fail on the client machine. MS tech support finally admitted it
was their bug, but had no fix other than a periodic reboot.
So, yes, malloc can fail from some other program running a small task in the
background and eating a few bytes at a time.
 
?

=?iso-8859-1?q?Nils_O=2E_Sel=E5sdal?=

I'm getting a little bit tired of writing

if (a = malloc(...) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?
Yes.
Not every gadget you program with C uses 'virtual memory'.
You might not even have any memory to use dynamically, as all is used by
the static allocated data, (while code squeezed in some ROMs)
Some sysadmin might limit you to only this'n'that much
memory for your use.
You might turn off swapping entierly.
Not all virtual memory space might be usable, as kernel maps
some, shared libraries might map some.
Your hardware might be faulty.
Your implementation might provide a low hard limit on how much
you can malloc.
 
M

Malcolm

Christian Bau said:
If you have a program with 100,000 bugs, which crashes every ten
minutes, it will be about two years before your bug is the one that gets
hit, so there is no point in fixing any bugs, right? Something somewhere
is wrong with that logic...
Say that you're building car components. There's no point providing a really
super spark plug, guaranteed for fifty years, when the rest of the
components will all start to fail after ten.
Similarly, there's not much point fixing a minor bug, which trips once every
two years, when you have 100,000 bugs causing a failure every ten minutes.
When you've got the failure rate down to once a month or so you can start
looking at the minor problems. Fix the serious bugs first.
If you run MS Windows then you can expect the system to crash once every few
days in general use anyway, so again there's not much practical difference
between 100% error free client software and software which crashes once or
twice a month.
 
J

James Dow Allen

I'm getting a little bit tired of writing

if ((a = malloc(...)) == NULL) {
// error code
}

I mean, is it really possible that a malloc call could fail, except in
the case of running out of virtual memory?

Several have responded, but none have provided the correct answers. :)

One big question is, who are you writing for? If you're writing
long-term industrial-strength software, you surely won't begrudge
a few keystrokes, so I'll assume your application is of limited
and well-defined application, where, as you say, malloc() just ain't
going to fail.

First, my library has a trivial routine mustmalloc() which does the
error test and aborts on failure, so you don't have to code
the error test elsewhere. You lose just four keystrokes ("must")
per invocation. You won't tailor a specific message for each malloc()
failure but who cares? "malloc() won't fail".

Please note that when malloc() *does* fail, you *will* get a descriptive
error message, even without the test. The message usually reads
"Segmentation violation: Core dumped." You know your users better than
I, and will know whether this message is convenient for them, but
the fact that *malloc() doesn't fail* should affect the trade-off.

(I've had only one malloc failure in the last 5-million keystrokes
and that occurred only because I was curious what it would take to
force malloc() to fail. YMMV.)

The reason I'm posting is that you will get several anal-retentive
responses mentioning Murphy's Law.
These messages aren't wrong, but reflect flawed and dogmatic priorities.
For example, responders will ignore that "Malloc failed" usually
isn't much more informative than "Segmentation violation: core dumped"
anyway. (In fact, the latter message may be more useful! It did dump
core, after all.)

There's little harm in a few extra keystrokes, so here the dogmatic
pedants aren't fully wrong.
Get me started though, and I'll tell about some million-dollar software
fiascoes caused by blind adherence to dogma.

James
 
K

Keith Thompson

Please note that when malloc() *does* fail, you *will* get a descriptive
error message, even without the test. The message usually reads
"Segmentation violation: Core dumped." You know your users better than
I, and will know whether this message is convenient for them, but
the fact that *malloc() doesn't fail* should affect the trade-off.

When malloc() fails, you *will* get undefined behavior if you try to
dereference the returned null pointer. On many (most?) systems, that
undefined behavior will take the form of a segmentation violation or
something similar, but (dogmatic pedant that I am) I don't
particularly want to depend on that.
 
K

Kenneth Brody

Keith said:
When malloc() fails, you *will* get undefined behavior if you try to
dereference the returned null pointer. On many (most?) systems, that
undefined behavior will take the form of a segmentation violation or
something similar, but (dogmatic pedant that I am) I don't
particularly want to depend on that.

I've seen systems that allow you to dereference (for reading) a NULL
pointer, and that memory always contained zeros. I don't recall how
many bytes were available at NULL, but enough so that "*(long *)NULL"
would return 0L. (More likely, it would be a case of string operations
acting as if it were a zero-length string.)

Of course, *NULL was write-protected.
 
R

RoSsIaCrIiLoIA

Two solutions come to my mind.

1: a=0; b=0; c=0; d=0;
a = malloc(.);
b = malloc(..);
c = malloc(...);
d = malloc(....);
// Don't use either a....d until you perform the test below.
if ( ! ( a && b && c && d ) )
{
// Deal with error;
free(a); free(b); free(c); free(d);...
....
 
K

Keith Thompson

RoSsIaCrIiLoIA said:
free(a); free(b); free(c); free(d);...
....

Initializing a, b, c, and d to 0 before the malloc() assignments is
pointless; they'll be overwritten with whatever malloc() returns.

As for the free()s you've added, that's fairly obviously covered by
"// Deal with error".
 
R

RoSsIaCrIiLoIA

Initializing a, b, c, and d to 0 before the malloc() assignments is
pointless; they'll be overwritten with whatever malloc() returns.

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);... }
 
J

James Dow Allen

Kenneth Brody said:
I've seen systems that allow you to dereference (for reading) a NULL
pointer, and that memory always contained zeros.

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.
Of course, *NULL was write-protected.

Yes. Returning to the thread's context, I think we all agree that
malloc()'ed memory should be written before read!

BTW, printf() will return a negative value ``if [and
only if] an output error is encountered.'' Do we insist on
checking for that every time printf() is called? Catching
that error is more relevant since it could be undetected, while,
in nearly all circumstances, a failed malloc() will quickly cause
a fault.

When you're crossing a busy street, do you stare at the heavens,
alert for a falling meteor you'll need to dodge? I thought not.
Similarly, any time wasted on errors that won't happen, is time
that could have been spent more usefully.

James
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top