malloc error checking

M

Marlene Stebbins

At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
}

for each individual call if there is a stylistically better way. How
would this be handled in commercial code?
 
D

David REsnick

Marlene said:
At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
}

for each individual call if there is a stylistically better way. How
would this be handled in commercial code?

Standard way is to write a wrapper you call in place of malloc
when you want this behavior. e.g.

void *safe_malloc(size_t size)
{
void *ret = malloc(size);
if (ret == NULL) {
fprintf(stderr, "malloc %u bytes failed", (unsigned)size);
exit(EXIT_FAILURE);
}

return ret;
}

That also has the advantage of letting you decide what to do on
malloc(0)... No guarantee the printf will work with no memory
available either, mind you. I added the size to your printf
and put it before the exit :) The size is useful in case a programming
error causes you to try to malloc(-1) or some such.

-David
 
K

Kornilios Kourtis

Marlene Stebbins said:
At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
^^^^^^^^^^^^^
this message will never be printed
because it's after the exit() call
for each individual call if there is a stylistically better way. How
would this be handled in commercial code?

You can use another wrapper function:

void *malloc_wrap(size_t size)
{
void *ret;

ret = malloc(size);
if (ret == NULL){
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAULURE);
}

return ret;
}
 
M

Michael Mair

David said:
Standard way is to write a wrapper you call in place of malloc
when you want this behavior. e.g.

void *safe_malloc(size_t size)
{
void *ret = malloc(size);
if (ret == NULL) {
fprintf(stderr, "malloc %u bytes failed", (unsigned)size);
exit(EXIT_FAILURE);
}

return ret;
}

That also has the advantage of letting you decide what to do on
malloc(0)... No guarantee the printf will work with no memory
available either, mind you. I added the size to your printf
and put it before the exit :) The size is useful in case a programming
error causes you to try to malloc(-1) or some such.

Note: Under C89, casting to unsigned long (and using %lu) is safer, as
we do not know how wide size_t actually is. We still might have the
situation that (size_t)((unsigned long)((size_t) -1)) != (size_t) -1.
Under C99 or with a C99 compliant standard library, use the length
modifier for size_t (z, i.e. %zu).


Cheers
Michael
 
R

Rouben Rostamian

At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
}

for each individual call if there is a stylistically better way. How
would this be handled in commercial code?

If all these calls occur within the body of a single function, then
you may do:


x1 = malloc(whatever);
x2 = malloc(whatever);
...
xn = malloc(whatever);

if (!x1 || !x2 || ... || !xn) {
fprintf(stderr, "malloc failed");
exit(EXIT_FAILURE);
}
 
M

Marlene Stebbins

Marlene said:
At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
}

I just noticed that I've got the exit and fprintf statements bass
ackwards. I should have had another cup of coffee before posting this.

MS
 
E

Emmanuel Delahaye

David REsnick wrote on 30/12/04 :
void *safe_malloc(size_t size)
{
void *ret = malloc(size);
if (ret == NULL) {
fprintf(stderr, "malloc %u bytes failed", (unsigned)size);
exit(EXIT_FAILURE);
}

return ret;
}

I would amend this code this way:

/* interface (.h) */

#define safe_malloc(size) \
safe_malloc_ (size, __FILE__, __LINE__)

void *safe_malloc_ (size_t size, char const *file, int line);


/* implementation (.c) */

void *safe_malloc_ (size_t size, char const *file, int line)
{
void *p = malloc(size);

if (p == NULL)
{
fprintf (stderr
, "malloc %lu bytes failed at %s:%d\n"
, (unsigned long)size
, file
, line
);
exit (EXIT_FAILURE);
}
return ret;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"C is a sharp tool"
 
E

Eric Sosman

Marlene said:
At one point in my program I have about a dozen calls to malloc. I want
to check for malloc failure, but I don't want to write:

if((buffer_x = malloc(BUFSIZE * sizeof(*buffer_x))) == NULL)
{
exit(EXIT_FAILURE);
fprintf(stderr, "malloc failed");
}

for each individual call if there is a stylistically better way. How
would this be handled in commercial code?

"It depends." Here are a few patterns:

if ((buff1 = malloc(size1)) == NULL
|| (buff2 = malloc(size2)) == NULL
...
|| (buff12 = malloc(size12)) == NULL) {
die_horribly();
}


for (i = 0; i < 12; ++i) {
if ((buff = malloc(size)) == NULL)
die_horribly();
}


/* malloc_wrapper() dies horribly on failure */
buff1 = malloc_wrapper(size1);
buff2 = malloc_wrapper(size2);
...
buff12 = malloc_wrapper(size12);


char *allbuffs = malloc(size1 + size2 + ... + size12);
if (allbuffs == NULL)
die_horribly();
buff1 = (Type1*)allbuffs;
buff2 = (Type2*)(allbuffs + size1);
...
buff12 = (Type12*)(allbuffs + size1 + size2 + ... + size11);

.... and many, many more.

There are at least two lessons in all this. First, there
are manymanymany ways to organize the handling of failures and
exceptional conditions in a program. Second, the choice of
method is usually not driven by the nature of the failure, but
by the structure of the program.
 
J

Jonathan Burd

Emmanuel said:
David REsnick wrote on 30/12/04 :



I would amend this code this way:

/* interface (.h) */

#define safe_malloc(size) \
safe_malloc_ (size, __FILE__, __LINE__)

void *safe_malloc_ (size_t size, char const *file, int line);


/* implementation (.c) */

void *safe_malloc_ (size_t size, char const *file, int line)
{
void *p = malloc(size);

if (p == NULL)
{
fprintf (stderr
, "malloc %lu bytes failed at %s:%d\n"
, (unsigned long)size
, file
, line
);
exit (EXIT_FAILURE);
}

ret isn't defined. He means return p, anyway.
 
E

Emmanuel Delahaye

(supersedes <[email protected]>)

David REsnick wrote on 30/12/04 :
void *safe_malloc(size_t size)
{
void *ret = malloc(size);
if (ret == NULL) {
fprintf(stderr, "malloc %u bytes failed", (unsigned)size);
exit(EXIT_FAILURE);
}

return ret;
}

I would amend this code this way:

/* interface (.h) */

#define safe_malloc(size) \
safe_malloc_ (size, __FILE__, __LINE__)

void *safe_malloc_ (size_t size, char const *file, int line);

/* implementation (.c) */

void *safe_malloc_ (size_t size, char const *file, int line)
{
void *p = malloc(size);

if (p == NULL)
{
fprintf (stderr
, "malloc %lu bytes failed at %s:%d\n"
, (unsigned long)size
, file
, line
);
exit (EXIT_FAILURE);
}
return p;
}

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
A

Artie Gold

Emmanuel said:
(supersedes <[email protected]>)

David REsnick wrote on 30/12/04 :



I would amend this code this way:

/* interface (.h) */

#define safe_malloc(size) \
safe_malloc_ (size, __FILE__, __LINE__)

void *safe_malloc_ (size_t size, char const *file, int line);

/* implementation (.c) */

void *safe_malloc_ (size_t size, char const *file, int line)
{
void *p = malloc(size);

if (p == NULL)
{
fprintf (stderr
, "malloc %lu bytes failed at %s:%d\n"
, (unsigned long)size
, file
, line
);

Ooooh. Not a great idea. If malloc() fails, fprintf (which likely uses
malloc() itself) may also fail.
exit (EXIT_FAILURE);
}
return p;
}
HTH,
--ag
 
E

Emmanuel Delahaye

Artie Gold wrote on 01/01/05 :
Ooooh. Not a great idea. If malloc() fails, fprintf (which likely uses
malloc() itself) may also fail.

Do you have any evidence of this ? Do you meant that the only option is

exit(EXIT_FAILURE);

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

"Clearly your code does not meet the original spec."
"You are sentenced to 30 lashes with a wet noodle."
-- Jerry Coffin in a.l.c.c++
 
C

Chris Croughton

Ooooh. Not a great idea. If malloc() fails, fprintf (which likely uses
malloc() itself) may also fail.

And the ceiling may fall in and crush the hard disk. That isn't a good
reason to not output diagnostics. What would you suggest instead?
Just:

with no explanation?

(There are many occasions when malloc may fail but fprintf will work
fine -- when the I/O buffers are already allocated, when the size
requested is unreasonably big, etc. If fprintf does fail, it is likely
to do so with a code dump which can be inspected, whereas just doing
exit will not be trapped.)

Chris C
 
A

Artie Gold

Chris said:
And the ceiling may fall in and crush the hard disk. That isn't a good
reason to not output diagnostics. What would you suggest instead?
Just:




with no explanation?

Point taken.
(There are many occasions when malloc may fail but fprintf will work
fine -- when the I/O buffers are already allocated, when the size
requested is unreasonably big, etc. If fprintf does fail, it is likely
to do so with a code dump which can be inspected, whereas just doing
exit will not be trapped.)
It's one of those situations where going into platform-specific-land
(using lower level calls) *may* be indicated. But again, I concede your
point.

--ag
 

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

Similar Threads


Members online

Forum statistics

Threads
474,157
Messages
2,570,879
Members
47,414
Latest member
djangoframe

Latest Threads

Top