From: fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON)
Subject: Re: Life, stderr, and everything (was Re: malloc() as a user...)
Organization: Computer Science, University of Melbourne, Australia
Date: Thu, 15 Oct 1992 06:43:58 GMT

ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes:

>In article <9228722.5429@mulga.cs.mu.OZ.AU>, fjh@munta.cs.mu.OZ.AU (Fergus James HENDERSON) writes:
>> If malloc fails, it may return an indication of the reason for failure
>> in errno, and if so then you use should use perror() to give that information
>> to the user.
>
>There has never been anything in the UNIX documentation to say that malloc()
>sets errno to any particular value.  There is nothing in the SVID to
>require it.  There is nothing in the ANSI C standard.  (We ordered a copy
>of POSIX.1 over a year ago.  We haven't got it yet.  So I don't know whether
>1003.1 says anything more about malloc(), but the last draft I saw didn't.)

That's why I say malloc() _may_ set errno, not that malloc() _will_ set errno.
Certainly it may not.
But if it does, then you _should_ call perror() to pass that information
on to the user.

>It is _only_ safe to use perror() for library functions which are
>_documented_ as setting errno.  In particular, the pundits in comp.std.c
>have ruled that this is a valid implementation of malloc():
>
>	void *malloc(size_t size) { return NULL; }
>
>Some UNIX manual pages _do_ state that malloc() calls sbrk(), but they
>do _not_ say that it assigns the same meanings to errno as sbrk().  I
>have been advised by UNIX wizards not to trust errno after malloc().
[...]

However, a _good_ implementation of malloc() _will_ set errno.
I would guess that most current implementations of malloc() do set errno,
although they might only have one error value, in which case it wouldn't
really provide much information.

>In summary, DO NOT CALL perror UNLESS the library function in question
>is DOCUMENTED as defining errno, or unless you are happy with garbage.

You omitted the code I posted from your reply.
If you read it carefully, you will see that I DON'T rely on malloc() setting
errno: first I clear errno, then I call malloc(), and then IF AND ONLY IF
errno is non-zero, I call perror(). That way, if malloc() _does_ set errno,
then you get a message like
	a.out: Unable to allocate enough memory: out of swap space.
and if it _doesn't_, then you get the less informative message
	a.out: Unable to allocate enough memory.

Here is the code again:

| extern char *progname;	/* main() should initialize this to argv[0] */
| 
| void fatal_error(const char *message, int errno) {
|     fflush(stdout);
|     if (progname) {
|         fprintf(stderr, "%s: ", progname);
|     }
|     if (errno) {
|         perror(message);
|     } else {
|         fprintf(stderr, "%s.\n", message);
|     }
|     exit(EXIT_FAILURE);
| }
| 
| void *safe_malloc(size_t size) {
|     void *ptr;
|     errno = 0;
|     ptr = malloc(size);
|     if (!ptr) {
| 	fatal_error("Unable to allocate enough memory", errno);
|     }
|     return ptr;
| }
| 

-- 
Fergus Henderson             fjh@munta.cs.mu.OZ.AU      
This .signature virus is a self-referential statement that is true - but 
you will only be able to consistently believe it if you copy it to your own
.signature file!
Newsgroups: comp.lang.c