Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 20 Dec 2000 09:41:11 -0600
From:      seebs@plethora.net (Peter Seebach)
To:        freebsd-hackers@freebsd.org
Subject:   Re: Why not another style thread? (was Re: cvs commit: src/lib/libc/gen .. 
Message-ID:  <200012201541.JAA15236@guild.plethora.net>
In-Reply-To: Your message of "20 Dec 2000 15:42:19 %2B0100." <5ld7enduic.fsf@assaris.sics.se> 

next in thread | previous in thread | raw e-mail | index | archive | help
In message <5ld7enduic.fsf@assaris.sics.se>, Assar Westerlund writes:
>Aled Morris <aledm@qix.co.uk> writes:
>> On Mon, 18 Dec 2000, Matt Dillon wrote:
>> >    void *
>> >    safe_malloc(int bytes) 
>> >    {
>> >	void *ptr;

>> >	if ((ptr = malloc(bytes)) == NULL)
>> >	    *(int *)0 = 1;	/* force seg fault */

>> Shouldn't you use "kill(0, SIGSEGV)" ?

>Why not err(3) or abort(3) ?

Okay, from a style standpoint, the basic problem is that this function
is a mistake.  Programs may have temp files open, they may have stty
settings to reset, there are tons of things you may need to do *BEFORE
EXITING*.  With that in mind, it becomes clear that you *can't* just
abort-on-failure.  Yes, it's a pain having every malloc() check for resources,
but you *have to do it*, or you will litter the disk with forgotten files,
break the user's terminal, and otherwise act like Microsoft Linux.

You just have to handle each failure as it comes.  Some require you to
punt and go back and clean up all your work and exit gracefully.  Others
may have options open, where you can free something up, or ask for a little
less.

Of course, this is all made harder by the current fad of overcommitting;
malloc can return a perfectly "good" pointer which you can't actually
dereference later.

I would like to point out that the original code is abjectly silly; after
all, the pointer is likely to get referenced soon enough.

At a bare minimum, the Correct Thing would be
	#define safe_malloc(x) safe_malloc_internal((x), __FILE__, __LINE__)

	void *safe_malloc(size_t bytes, char *file, int line)
	{
		void *p = malloc(bytes);
		if (p == NULL) {
			fprintf(stderr, "can't allocate %lu bites at file %s, line %d.",
				(unsigned long) x, __FILE__, __LINE__);
			exit(EXIT_FAILURE);
		}
	}

But that still presupposes it ever makes sense to just puke and die on a
failed malloc.

It might be reasonable to omit the exit(), and then, even if you segfault
immediately after the malloc, you'll have logged what killed you.

(In an ideal world, you'd have the program name in here.)

(In an even more ideal world, you'd have C99, and you'd use %ju, and
cast x to uintmax_t, because we don't know how large size_t will be
in the future.)

But really, the best implementation of safe_malloc is
	void *safe_malloc(char bytes) /* might as well, who cares? */
	{
	#error "Malloc is about as safe as free climbing on large mountains."
	}

-s


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200012201541.JAA15236>