Date: Sat, 2 May 2009 18:35:35 +0200 From: Erik Trulsson <ertr1013@student.uu.se> To: Andrew Brampton <brampton+freebsd-hackers@gmail.com> Cc: freebsd-hackers@freebsd.org Subject: Re: Definition of NULL Message-ID: <20090502163535.GA17027@owl.midgard.homeip.net> In-Reply-To: <d41814900905020859q4faff431p8819aaf38dfe9e78@mail.gmail.com> References: <d41814900905020859q4faff431p8819aaf38dfe9e78@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
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 -- <Insert your favourite quote here.> Erik Trulsson ertr1013@student.uu.se
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20090502163535.GA17027>