Topic: Does the proposed resolution to core issue 232 allow null references?


Author: william.m.miller@gmail.com ("William M. Miller")
Date: Thu, 31 Mar 2005 05:05:46 GMT
Raw View
Victor Bazarov wrote:
> "William M. Miller" wrote:
>
>>[..]  We wanted to deal with this more generally, as well as
>>the one-past-the-end pointer; that is why the proposed wording
>>introduces the "empty lvalue" and forbids applying the
>>lvalue-to-rvalue conversion to it.
>
>
> OK, thanks.
>
> What I get from all this is that
>
>     sometype *p = 0;
>     sometype &r = *p;
>
> is not ill-formed, only produces undefined behaviour.  Correct?
> Or does it?  Essentially, 'r' cannot be "used" in any way, except
> to take its address.  Am I right?  So we essentially allow the
> existence of such reference whose addressed object is "not there"
> as it were.  What is it if not a "null reference"?
>
> Please clarify.

The initialization of "r" produces undefined behavior, because it
is, in general, impossible tell whether "p" has a null pointer
value or not; categorizing something as ill-formed implies that
it can be diagnosed at compile time.

The fact that it's undefined behavior means that you can't rely
on being able to perform the initialization at all (for instance,
a checking implementation might halt execution immediately when
the initialization is attempted), so it's meaningless to say that
"r" can be "used" at all, whether to take its address or anything
else.  Undefined behavior does not "allow the existence of such a
reference" -- it means that if you try to produce one, all bets
are off and the implementation can do anything at all, including
crashing the program.

You're right, that is indeed a "null reference," and it is
prohibited.

>> As I said, though, this
>>change does not affect the status of "null references" at all.
>>The only thing that changes with references is the explicit
>>acknowledgment that they can be bound to "pre-natal" and
>>"post-mortem" objects (which can already be referred to by lvalues).
>
>
> OK.  And at the same time lvalue-to-rvalue conversion on those
> objects leads to undefined behaviour, yes?  I mean, if we try to
> apply an operation that requires fetching the value of an object
> that hasn't been constructed or has been destroyed, then KABOOOM!
> Doesn't really change a thing WRT "null references", does it?

That's right.  The restrictions are in 3.8p6 and include the
lvalue-to-rvalue conversion, as well as several other operations.
  And, as you said, this is unrelated to "null references."  The
only reason I mentioned it is that the wording in the current
Standard that prevents creating "null references" ("A reference
shall be initialized to refer to a valid object...") is being
changed (if the resolution is adopted), so I wanted to illuminate
the reason for the change and explain that "null references" are
still prohibited.

--
William M. (Mike) Miller | Edison Design Group, Inc.
william.m.miller@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: william.m.miller@gmail.com ("William M. Miller")
Date: Mon, 4 Apr 2005 15:40:03 GMT
Raw View
Victor Bazarov wrote:
> johnchx2@yahoo.com wrote:
>>Perhaps I'm over-interpreting, but the above reads to me as if you
>>believed that the language (currently) guarantees that the reference
>>ri denotes a live object in any well-formed program.  Am I
>>misunderstanding?
>
>
> Doesn't it?  I mean, doesn't language (currently) guarantee that the
> reference 'ri' is initialised to refer to a valid object?  Are you
> saying that currently it's not so, and my regrets about "where the
> language is headed" were unfounded since it's already "there"?
>
> It is impossible to initialise a function argument of type 'a reference
> to T' with anything except an object of T or an object convertible to T
> (please see 8.5.3).  [As Mike has pointed out, the language is still going
> to enforce that, so my fear that the language is headed in the wrong
> direction has no foundation, as I know realize]

There is a difference between requiring something and
"guaranteeing" or "enforcing" it.  Creating a "null reference" is
undefined behavior, and as with all cases of undefined behavior,
one possible outcome is that the operation appears to work
without producing an error.  It also might mean that the program
aborts or that it displays the first two million digits of pi.

The Standard says that it's not permitted to create a "null
reference."  It doesn't require an implementation to prevent you
from doing so.  It's up to you as to whether you think this error
will be sufficiently common as to be worth spending programming
and execution time checking for it.

All I said was that there are no changes contemplated on the
handling of "null references," so if you're not checking for them
today and are happy with the results, there's no reason to change
your current practice.

--
William M. (Mike) Miller | Edison Design Group, Inc.
william.m.miller@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: falk.tannhauser@crf.canon.fr (=?ISO-8859-1?Q?Falk_Tannh=E4user?=)
Date: Wed, 23 Mar 2005 19:46:02 GMT
Raw View
Victor Bazarov wrote:
> I will now have to begin to write code like this:
>
>     void foo(int& ri) {
>         if (&ri != 0) // it's a null reference
>             ;// do something to use 'ri'
>     }
> Because this seems where the language is headed.  Pity.

I would hate this, too. But have you checked
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#453>?

Falk

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Fri, 25 Mar 2005 05:14:19 GMT
Raw View
Falk Tannh=E4user wrote:
> Victor Bazarov wrote:
>=20
>> I will now have to begin to write code like this:
>>
>>     void foo(int& ri) {
>>         if (&ri !=3D 0) // it's a null reference
>>             ;// do something to use 'ri'
>>     }
>> Because this seems where the language is headed.  Pity.
>=20
>=20
> I would hate this, too. But have you checked
> <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#453>?

That only means the Committee has some things to do (resolving conflicts
between allowing to dereference a null pointer thus forming a null ref
and the proposed resolution for 453).  Meanwhile I will start writing
that code "just in case".  I bet I am not alone.  I remember the days
when testing 'this' for being null was necessary inside member functions.

V

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: william.m.miller@gmail.com ("William M. Miller")
Date: Tue, 29 Mar 2005 21:47:23 GMT
Raw View
Victor Bazarov wrote:
> I give up.  In my understanding the whole idea of "using" a null pointer
> (dereferencing and otherwise) was linked to the fact that on a certain
> hardware even _loading_ a special address register can cause a hardware
> exception if the address is not valid.  The Committee seems to be going
> in circles around the "using" issue WRT pointers (null, invalid,
> one-pass-the-end).  IANALL.  Sorry I ever mentioned null references.
> I will now have to begin to write code like this:
>
>     void foo(int& ri) {
>         if (&ri != 0) // it's a null reference
>             ;// do something to use 'ri'
>     }
>
> Because this seems where the language is headed.  Pity.

First, as the person responsible for drafting the proposed
resolutions for issues 232 and 453, I can state categorically
that the intent is _not_ to allow "null references."  In fact,
the wording has been very carefully crafted not to change the
status of "null references" at all -- they have always been
undefined behavior and will continue to be undefined behavior. If
you are not writing code like the above today, I don't see any
reason for you to start doing so in the future.

The other point I'd like to make is that there is a difference
between null pointer values and invalid pointer values.  Null
pointer values are valid and must cause a trap only when used to
fetch or store data.  On the other hand, an invalid pointer --
the old address after freeing an object, or an uninitialized
pointer value -- does have the characteristic you described: an
implementation is allowed to fault even on accessing such a value
itself, without attempting to indirect through it to access
memory.  The one-past-the-end pointer is also required to be
valid, although not necessarily to point to an object of the
associated type (see the footnote in 5.7 about needing only one
byte after the end of an array to support this requirement).

C99 has the concept of a "trap representation" -- a bit pattern
that does not represent a value of the type and that causes
undefined behavior if fetched.  Another way of viewing invalid
pointers is that the value might be a trap representation; a null
pointer or a pointer one-past-the-end of an array must _not_ be a
trap representation.

One of the things we're trying to capture by this change in
wording is that there is a distinction between unary * appearing
in the source and actually using the operand to fetch or store
memory.  C99, for instance, deals with part of this in the way
they handle & and * -- applying unary & to the result of unary *
makes both of them a no-op, even if the operand of * is a null
pointer.  We wanted to deal with this more generally, as well as
the one-past-the-end pointer; that is why the proposed wording
introduces the "empty lvalue" and forbids applying the
lvalue-to-rvalue conversion to it.  As I said, though, this
change does not affect the status of "null references" at all.
The only thing that changes with references is the explicit
acknowledgment that they can be bound to "pre-natal" and
"post-mortem" objects (which can already be referred to by lvalues).

--
William M. (Mike) Miller | Edison Design Group, Inc.
william.m.miller@gmail.com

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: v.Abazarov@comAcast.net (Victor Bazarov)
Date: Tue, 22 Mar 2005 21:26:17 GMT
Raw View
Llewelly wrote:
> [...]
> So I would appreciate it if you would explain why you think
>
>     T* p= 0;
>     T& r= *p;
>
> either requires the lvalue-to-rvalue conversion when initializing the
>     reference, or would have undefined behavior for some other reason,
>     if the proposed resolution to core issue 232 was accepted as it
>     stands today.
>
> (Despite all appearances, I'm *not* in favor of extending the standard
>     to support null references.)

I give up.  In my understanding the whole idea of "using" a null pointer
(dereferencing and otherwise) was linked to the fact that on a certain
hardware even _loading_ a special address register can cause a hardware
exception if the address is not valid.  The Committee seems to be going
in circles around the "using" issue WRT pointers (null, invalid,
one-pass-the-end).  IANALL.  Sorry I ever mentioned null references.
I will now have to begin to write code like this:

     void foo(int& ri) {
         if (&ri != 0) // it's a null reference
             ;// do something to use 'ri'
     }

Because this seems where the language is headed.  Pity.

V

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]