From owner-freebsd-hackers@FreeBSD.ORG Sat May 2 16:50:52 2009 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9C9BE106566B for ; Sat, 2 May 2009 16:50:52 +0000 (UTC) (envelope-from erikt@midgard.homeip.net) Received: from ch-smtp01.sth.basefarm.net (ch-smtp01.sth.basefarm.net [80.76.149.212]) by mx1.freebsd.org (Postfix) with ESMTP id 2F2438FC26 for ; Sat, 2 May 2009 16:50:51 +0000 (UTC) (envelope-from erikt@midgard.homeip.net) Received: from c83-255-48-78.bredband.comhem.se ([83.255.48.78]:50818 helo=falcon.midgard.homeip.net) by ch-smtp01.sth.basefarm.net with esmtp (Exim 4.69) (envelope-from ) id 1M0IBe-00067F-4b for freebsd-hackers@freebsd.org; Sat, 02 May 2009 18:35:40 +0200 Received: (qmail 29888 invoked from network); 2 May 2009 18:35:35 +0200 Received: from owl.midgard.homeip.net (10.1.5.7) by falcon.midgard.homeip.net with ESMTP; 2 May 2009 18:35:35 +0200 Received: (qmail 17087 invoked by uid 1001); 2 May 2009 18:35:35 +0200 Date: Sat, 2 May 2009 18:35:35 +0200 From: Erik Trulsson To: Andrew Brampton Message-ID: <20090502163535.GA17027@owl.midgard.homeip.net> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.19 (2009-01-05) X-Originating-IP: 83.255.48.78 X-Scan-Result: No virus found in message 1M0IBe-00067F-4b. X-Scan-Signature: ch-smtp01.sth.basefarm.net 1M0IBe-00067F-4b 5b478a627850c02c1b8e9d6a3f3afa1f Cc: freebsd-hackers@freebsd.org Subject: Re: Definition of NULL X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 02 May 2009 16:50:53 -0000 On Sat, May 02, 2009 at 04:59:03PM +0100, Andrew Brampton wrote: > I'm writing a C++ Kernel Module, and one thing that has been bugging > me is the kernel's definition of NULL. Is the use of C++ inside the kernel really supported? I don't think so, but I could be wrong. > > sys/sys/_null.h (in CURRENT): > > #if defined(_KERNEL) || !defined(__cplusplus) > #define NULL ((void *)0) > #else > #if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 > #define NULL __null > #else > #if defined(__LP64__) > #define NULL (0L) > #else > #define NULL 0 > #endif /* __LP64__ */ > #endif /* __GNUG__ */ > #endif /* _KERNEL || !__cplusplus */ > > >From what I've read online the definition of NULL in C is (void *)0, > whereas in C++ it should be 0, or 0L (on 64bit machines). Not quite. Any of those (as well as a whole bunch more) are legal definitions of NULL in C. NULL is defined (in the C standard) to be a null pointer constant. A null pointer constant is defined as a constant integer expression with value zero, or such an expression cast to (void*). (In C++ it the cast to (void*) is not allowed.) This means that it would be perfectly legal (but of dubious utility) to have NULL defined as (5*5L+('1'-'0')-26) for example. The decision to define NULL as 0 or 0L or ((void*)0) is pretty much just a question of which buggy programs one wishes to break, or hide the bugs in. A correct C program should work regardless of which of those is used. > > Now, my C++ kernel module is built with _KERNEL definited, like any > other C kernel module. This leads to NULL being defined incorrectly. > > So I have a question and two suggestions. Firstly, why is the #if > defined(_KERNEL) in _null.h? Is it to stop userland application > applications picking up this definition? Or for another reason? Perhaps to stop people from mistakenly using C++ inside the kernel? > > and two, how about we change the first line of _null.h so that we use > a && instead of a || like so: > #if defined(_KERNEL) && !defined(__cplusplus) > > That should ensure the definition is correct. Or, a more radical > approach, we could remove the check for _KERNEL, since I can't figure > out why it is needed and do something like: > > #if defined(__GNUG__) && defined(__GNUC__) && __GNUC__ >= 4 > # define NULL __null > #elif !defined(__cplusplus) > # define NULL ((void *)0) > #elif defined(__LP64__) > # define NULL (0L) > #else > # define NULL 0 > #endif > > That way, if we are using GCC 4+ we use their __null definition, > otherwise if we are not c++ we use the standard (void *)0, and then if > we are 64bit we use 0L, and finally anything else uses 0. A quick > amd64 kernel compile seems to allow my new definition If you want to keep things simple you could just define NULL as 0 everywhere, and see what bugs are exposed that way. > > I hope this makes sense, and I welcome all feedback. > Andrew -- Erik Trulsson ertr1013@student.uu.se