Re: ffi idea: strip null pointers

  • From: Cosmin Apreutesei <cosmin.apreutesei@xxxxxxxxx>
  • To: luajit@xxxxxxxxxxxxx
  • Date: Wed, 6 Jun 2012 07:41:00 +0300

Sorry but I couldn't understand from your comments what is your
position about ffi converting null pointers to nil.

I doubt luajit would ever work on a platform for which NULL isn't
zero[1], but that wouldn't even be an issue since the ffi already
knows how to convert a nil to a NULL so it could as well do the
reverse.

Lemme put it another way: what object does the NULL address hold that
the type system doesn't want us to trash, a foo* or a bar* ? :)

[1] http://c-faq.com/null/machexamp.html

On Tue, Jun 5, 2012 at 7:59 PM, Sean Conner <sean@xxxxxxxxxx> wrote:
> It was thus said that the Great Cosmin Apreutesei once stated:
>>
>> In static languages people have to reserve a segment from the range of
>> a scalar type for special values like "error" or "unknown". So they
>> use -1 to signal an error case and the address 0 (aka NULL) to specify
>> lack of a value. In C, NULL is just a convention. From the pov. of the
>> language, the zero address is as valid as any other, hence you can't
>> pass a NULL bar* for a foo*. But everybody on earth reserves the
>> address 0 for the special meaning missing/empty/not-valid/unknown/etc.
>> which is _the same meaning_ for foo* as it is for bar* hence it is
>> _logically transferable_ from foo* to bar*, but C doesn't let you do
>> that because it doesn't know anything about NULL since that's just a
>> convention, necessary in any static-typed language.
>
>  In C, the use of the value 0 in a pointer context converts that 0 to a
> null pointer [1] of the type of 'void *' (the generic pointer in ANSI C).
> Also in C, any pointer can be converted to a 'void *' with no cast, and a
> 'void *' can be converted to any type of pointer with no cast.  So the
> following:
>
>        foo__t *foo;
>        bar__t *bar;
>
>        foo = malloc(5);
>        bar = foo;
>
> will cause a compiler error since you are trying to assign a 'foo__t *' to a
> 'bar__t *'.  But this:
>
>        foo__t *foo;
>        void   *p;
>        bar__t *bar;
>
>        foo = malloc(5);
>        p   = foo;
>        bar = p;
>
> will compile without error (or warnings).  That's because the pointer of
> 'foo__t *' goes through a 'void *' variable.  So, you can't do:
>
>        foo = (bar__t *)NULL;
>        bar = (foo__t *)NULL;
> but you can do
>
>        foo = NULL;
>        bar = NULL;
>
> And of course you can always do:
>
>        foo = (foo__t *)bar;
>        bar = (bar__t *)foo;
>
> [1]     There is a distinction between the value 0 used in a pointer context
>        in source code, and an actual "null" pointer as defined by the CPU
>        architecture [2].  Yes, many CPUs these days will also use the value
>        of 0 as an invalid pointer, but that's not mandated!  There could be
>        an architecure where an invalid pointer is actually all ones.  On
>        such a system, NULL is still defined as '0' [3] but internally the
>        compiler converts such a value to all ones to store in to the actual
>        pointer variable.
>
> [2]     That is, if the CPU architecture actually *has* a concept of an
>        invalid pointer.  If a CPU has no concept of an invalid pointer,
>        then a value is ussually used.  It could be all zeros.  It could be
>        all ones.  It could be alternating ones and zeros.  It just has to
>        be treated as an "invalid" address in software.
>
> [3]     or sometimes '(void *)0'
>
>> In Lua we no longer have to revert to tricks like NULL. We don't think
>> having a "nil string" incompatible with a "nil number" as a neat idea
>> either. The ffi is a Lua API not a C API and deals with C APIs not
>> with the C language, it doesn't have to copy C's world-view if it's
>> not useful. This "guarding" against assigning a NULL foo* to a bar* is
>> not a useful property in Lua (I think it's not useful in C either, you
>> just can't have it otherwise in a static language).
>
>  In Lua, values have types, not variables.  And because of that, Lua can
> make the distinction between 'undefined' and 'defined' (and thus, only has
> one type of 'nil', which is 'nil).  C doesn't have that distinction, except,
> somewhat, with pointers and NULL.  But just declaring a pointer in C:
>
>        foo__t *foo;
>
> doesn't make it 'undefined' (per the Lua meaning)---the value is whatever
> happens to be in the memory locations that make up the pointer.  That could
> be 0 (which doesn't imply an invalid pointer---that depends upon the
> architecure); it could be 42, or it could be some random bit pattern.  The
> use of foo, prior to being initialized, is undefined (it may read/write some
> memory somewhere; it could crash the program; again, it's architecturally
> dependent).
>
>  -spc
>
>

Other related posts: