C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

How to avoid null references ?
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards
View previous topic :: View next topic  
Author Message
Yannick Moy
Guest





PostPosted: Thu Feb 17, 2005 6:25 pm    Post subject: How to avoid null references ? Reply with quote



In previous conversations on this newsgroup, it is said that null
references qualify as "undefined behaviour", as said in standard
8.3.2.4:
"a null reference cannot exist in a well-defined program, because the
only way to create such a reference would be to bind it to the object
obtained by dereferencing a null pointer".

The problem is that it is way too easy to create a null reference,
without any "bad" cast or overflow on a stack array ...
e.g. the following:

int& r = *p; // with p of type int*

Nobody says here p should not be null, and although the standard
considers this as a bad operation if p is null, compilers will store
the possibly null address contained in p into r. (Are there any
compilers that would crash at run-time on such a construct ?)

Why not prevent this by allowing to bind references only to
non-dereferenced expressions, so that the previous line becomes
invalid C++ ?
If there is a need for such an operation, either it can be made
explicit that there is a dereference:

int i = *p;
in& r = i;

or, if the object pointed-to must stay at its current location (stack
or heap), or to avoid a copy-constructor if the object pointed-to is
of class type, we can consider a template function object or a
specific reference_cast operator that takes a pointer and returns a
reference to the pointed-to location:

int& r = reference_cast<int&>(p);

This template function object or operator would check that p is not
null, and throw an exception in case it is null.

Is it a problem that's never seen in real-life code ?
Are there other solutions to solve it ?
Thanks.

---
[ 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 ]

Back to top
Ron Natalie
Guest





PostPosted: Fri Feb 18, 2005 2:52 am    Post subject: Re: How to avoid null references ? Reply with quote



Yannick Moy wrote:

Quote:
The problem is that it is way too easy to create a null reference,
without any "bad" cast or overflow on a stack array ...
e.g. the following:

int& r = *p; // with p of type int*

To validate this the compiler would have to check the nullness of
p when doing the initialization. When that might happen is dubious
because at runtime there might not even be any concrete "r" variable
that gets initialized. The compiler in many cases just substitutes
the *p consruct wherever r is used.

You'd have a hard time getting the cycle counters to agree to an
explicit null check here anymore than any other use of *p.

Quote:

Nobody says here p should not be null, and although the standard
considers this as a bad operation if p is null, compilers will store
the possibly null address contained in p into r. (Are there any
compilers that would crash at run-time on such a construct ?)

There's no indication that anything has to be stored at all.

Quote:
Why not prevent this by allowing to bind references only to
non-dereferenced expressions, so that the previous line becomes
invalid C++ ?
Fine if you're talking about ints. A little bit more onerous with

larger types (which is presumbaly why you were dealing with pointers
and references anyhow).

---
[ 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 ]


Back to top
Yannick Moy
Guest





PostPosted: Fri Feb 18, 2005 2:39 pm    Post subject: Re: How to avoid null references ? Reply with quote



Ron Natalie wrote:

Quote:
You'd have a hard time getting the cycle counters to agree to an
explicit null check here anymore than any other use of *p.

A use of int& or class S& is not part of the C core of C++.
We can expect some more robust treatment from the language and
compilers on a reference that on raw pointers, don't you think ?
Moreover, this null check would be there only when a reference is
taken from a dereferenced raw pointer, that's all.

Quote:
There's no indication that anything has to be stored at all.

I agree, the goal of the check is to maintain the invariant that
references do not hold null pointers, whatever the translation of
these references by the compiler is.

Quote:
Why not prevent this by allowing to bind references only to
non-dereferenced expressions, so that the previous line becomes
invalid C++ ?
Fine if you're talking about ints. A little bit more onerous with
larger types (which is presumbaly why you were dealing with pointers
and references anyhow).

What about a simple function object ?

template <class T> struct reference_cast {
T& operator()(T* p) {
if (p == 0) throw std::bad_cast();
return *p;
}
};

You would use it simply like:

int& r = reference_cast<int>()(p); // for int
S& r = reference_cast<S>()(p); // for S

with no copy-constructor involved.
Maybe it is preferable in this case to make the operator() inline ?
Then if the compiler knows that (p == 0) is always false, it can
safely remove the check, which makes the program as simple as the
original

int& r = *p;

---
[ 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 ]


Back to top
johnchx2@yahoo.com
Guest





PostPosted: Sat Feb 19, 2005 7:44 am    Post subject: Re: How to avoid null references ? Reply with quote

Yannick Moy wrote:
Quote:
The problem is that it is way too easy to create a null reference,
without any "bad" cast or overflow on a stack array ...
e.g. the following:

int& r = *p; // with p of type int*


I think the real problem here is that the code potentially dereferences
a null pointer. It has nothing to do with whether or not you go on to
bind the lvalue to a reference.

So the question really ought to be: how do we ensure that we never
dereference a null pointer?

I think there's something to be said for a coding convention that says
that the *only* reason to dereference a pointer is to initialize a
reference, immediately after explicitly testing that the pointer is
non-null.

Of course there are a few (chuckle) practical difficulties. Do we
really want to outlaw operator->()? What about smart pointers? What
about those C API's that insist on returning pointers but that
guarantee that they are non-null...is a redundant test really
necessary?

But I do think it's worth at least being aware that every pointer
dereferencing operation is making an assumption that is not guaranteed
by the type system, and is therefore hazardous to one's health.

---
[ 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 ]


Back to top
richard@ex-parrot.com
Guest





PostPosted: Tue Feb 22, 2005 6:57 pm    Post subject: Re: How to avoid null references ? Reply with quote


Yannick Moy wrote:
Quote:
What about a simple function object ?

template <class T> struct reference_cast {
T& operator()(T* p) {
if (p == 0) throw std::bad_cast();
return *p;
}
};

What's wrong with a simple template function?

template <class T>
T& reference_cast( T* p ) {
/* as before */
}

Much neater -- you don't need the extra paretheses when using it. Or
if you wanted to explicitly prevent template argument deduction (for
example, to require a cast-like syntax), then just do

template <class T>
T& reference_cast( typename boost::mpl::identity<T*>::type p ) {
/* as before */
}

Quote:
Maybe it is preferable in this case to make the operator() inline ?

It is inline. Any function defined within the body of the class is
implicitly inline.

--
Richard Smith

---
[ 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 ]


Back to top
Roger Orr
Guest





PostPosted: Wed Feb 23, 2005 9:44 pm    Post subject: Re: How to avoid null references ? Reply with quote

I'd like to pick up on your last-but-one question:

Quote:
Is it a problem that's never seen in real-life code ?

It is seen, sometimes, in my experience. However using a null reference
usually generates an easily debuggable fault.
I think it is less of a problem than dangling references, which cause other
problems like memory corruption.
There is also a problem with calling through a null 'this' pointer:-

p->aMethod();

although 'undefined behaviour' depending on whether 'aMethod()' accesses
instance data it may not cause any apparent grief.

Regards,
Roger Orr
--
MVP in C++ at www.brainbench.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 ]


Back to top
Thorsten Ottosen
Guest





PostPosted: Sat Feb 26, 2005 3:41 pm    Post subject: Re: How to avoid null references ? Reply with quote



"Yannick Moy" <moy (AT) polyspace (DOT) com> wrote

Quote:
In previous conversations on this newsgroup, it is said that null
references qualify as "undefined behaviour", as said in standard
8.3.2.4:
"a null reference cannot exist in a well-defined program, because the
only way to create such a reference would be to bind it to the object
obtained by dereferencing a null pointer".

the standard is going to change on this matter; the lates from the October
meeting says that

"
Proposed resolution (October, 2004):
(Note: the resolution of issue 453 also resolves part of this issue.)

Add the indicated words to 3.10 basic.lval paragraph 2:
An lvalue refers to an object or function or is an empty lvalue (5.3.1
expr.unary.op).

Add the indicated words to 5.3.1 expr.unary.op paragraph 1:
The unary * operator performs indirection: the expression to which it is
applied shall be a pointer to an object type, or a pointer to a function type
and the result is an lvalue referring to the object or function to which the
expression points, if any. If the pointer is a null pointer value (4.10
conv.ptr) or points one past the last element of an array object (5.7
expr.add), the result is an empty lvalue and does not refer to any object or
function. An empty lvalue is not modifiable. If the type of the expression is
"pointer to T," the type of the result is "T." [Note: a pointer to an
incomplete type (other than cv void) can be dereferenced. The lvalue thus
obtained can be used in limited ways (to initialize a reference, for example);
this lvalue must not be converted to an rvalue, see 4.1 conv.lval.-end note]

Add the indicated words to 4.1 conv.lval paragraph 1:
If the object to which the lvalue refers is not an object of type T and is not
an object of a type derived from T, or if the object is uninitialized, or if
the lvalue is an empty lvalue (5.3.1 expr.unary.op), a program that
necessitates this conversion has undefined behavior.

Change 1.9 intro.execution as indicated:
Certain other operations are described in this International Standard as
undefined (for example, the effect of dereferencing the null pointer division
by zero)"

AFAICT, null references are already allowed on many compilers.

-Thorsten


---
[ 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 ]


Back to top
Thomas Mang
Guest





PostPosted: Sun Feb 27, 2005 10:00 pm    Post subject: Re: How to avoid null references ? Reply with quote


""Thorsten Ottosen"" <nesotto (AT) cs (DOT) auc.dk> schrieb im Newsbeitrag
news:421c96b2$0$29273$14726298 (AT) news (DOT) sunsite.dk...
Quote:


"Yannick Moy" <moy (AT) polyspace (DOT) com> wrote in message
news:d45930e4.0502162259.75655cd5 (AT) posting (DOT) google.com...
| In previous conversations on this newsgroup, it is said that null
| references qualify as "undefined behaviour", as said in standard
| 8.3.2.4:
| "a null reference cannot exist in a well-defined program, because the
| only way to create such a reference would be to bind it to the object
| obtained by dereferencing a null pointer".

the standard is going to change on this matter; the lates from the October
meeting says that

"
Proposed resolution (October, 2004):
(Note: the resolution of issue 453 also resolves part of this issue.)

Add the indicated words to 3.10 basic.lval paragraph 2:
An lvalue refers to an object or function or is an empty lvalue (5.3.1
expr.unary.op).

Add the indicated words to 5.3.1 expr.unary.op paragraph 1:
The unary * operator performs indirection: the expression to which it is
applied shall be a pointer to an object type, or a pointer to a function
type
and the result is an lvalue referring to the object or function to which
the
expression points, if any. If the pointer is a null pointer value (4.10
conv.ptr) or points one past the last element of an array object (5.7
expr.add), the result is an empty lvalue and does not refer to any object
or
function. An empty lvalue is not modifiable. If the type of the expression
is
"pointer to T," the type of the result is "T." [Note: a pointer to an
incomplete type (other than cv void) can be dereferenced. The lvalue thus
obtained can be used in limited ways (to initialize a reference, for
example);
this lvalue must not be converted to an rvalue, see 4.1 conv.lval.-end
note]

Add the indicated words to 4.1 conv.lval paragraph 1:
If the object to which the lvalue refers is not an object of type T and is
not
an object of a type derived from T, or if the object is uninitialized, or
if
the lvalue is an empty lvalue (5.3.1 expr.unary.op), a program that
necessitates this conversion has undefined behavior.

Change 1.9 intro.execution as indicated:
Certain other operations are described in this International Standard as
undefined (for example, the effect of dereferencing the null pointer
division
by zero)"


I don't get this. First, I was shocked when I read that modifications. Now I
have the hope I am simply misunderstanding what it means.

Could you please provide real-world examples what an empty lvalue etc. is,
and how it is intended to be used?


Thomas


---
[ 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 ]


Back to top
Thorsten Ottosen
Guest





PostPosted: Tue Mar 01, 2005 2:18 am    Post subject: Re: How to avoid null references ? Reply with quote

""Thomas Mang"" <nospam (AT) nospam (DOT) ucar.edu> wrote

Quote:

""Thorsten Ottosen"" <nesotto (AT) cs (DOT) auc.dk> schrieb im Newsbeitrag

the standard is going to change on this matter; the lates from the October
meeting says that

I don't get this. First, I was shocked when I read that modifications. Now I
have the hope I am simply misunderstanding what it means.

Could you please provide real-world examples what an empty lvalue etc. is,
and how it is intended to be used?

int* p = 0;
...
int& r = *p;
...
if( &r != 0 )
{
r = 5;
}

-Thorsten


---
[ 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 ]


Back to top
Yannick Moy
Guest





PostPosted: Thu Mar 03, 2005 6:27 am    Post subject: Re: How to avoid null references ? Reply with quote

Do you know what will be the semantics of a dynamic_cast on a null
reference then ? e.g.:

A* p = 0;
A& r = *p;
B& r2 = dynamic_cast<B&>(r);

The standard says so far:
"If the value of v is a null pointer value in the pointer case, the
result is the null pointer value of type R."

Will this translate to:
"If the value of v is a null reference in the reference case, the
result is the null reference value of type R."

Thanks.

---
[ 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 ]

Back to top
Marc Schoolderman
Guest





PostPosted: Sun Mar 06, 2005 7:13 am    Post subject: Re: How to avoid null references ? Reply with quote

Thorsten Ottosen wrote:

Quote:
Add the indicated words to 5.3.1 expr.unary.op paragraph 1:
The unary * operator performs indirection: the expression to which it is
applied shall be a pointer to an object type, or a pointer to a function type
and the result is an lvalue referring to the object or function to which the
expression points, if any.

Because of the "if any", is this line of code still allowed?

int a[3]; int* end = &a[3]; // instead of a+3

Under the present wording, I believe this is valid because *(a+3) does
produce an lvalue - it would be undefined to convert it into an rvalue,
but this doesn't happen because of the & operator, so it's ok.

After these modifications, "a[3]" is an empty lvalue. What exactly does
it mean to take the address of an empty lvalue? The address-of operator
only says "The result of the unary & operator is a pointer to its operand.".

For obvious reasons, all 'empty lvalues' will 'retain' their address,
but I'm fuzzy how these changes state this.

~Marc

---
[ 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 ]


Back to top
Marc Schoolderman
Guest





PostPosted: Mon Mar 07, 2005 4:49 pm    Post subject: Re: How to avoid null references ? Reply with quote

Thorsten Ottosen wrote:

Quote:
| Could you please provide real-world examples what an empty lvalue etc. is,
| and how it is intended to be used?
int* p = 0;
int& r = *p;

Uh, check issue 453 - it explicitly forbids this.

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#453

---
[ 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 ]


Back to top
Thomas Mang
Guest





PostPosted: Thu Mar 10, 2005 3:10 am    Post subject: Re: How to avoid null references ? Reply with quote


""Thorsten Ottosen"" <nesotto (AT) cs (DOT) auc.dk> schrieb im Newsbeitrag
news:42234bc9$0$29273$14726298 (AT) news (DOT) sunsite.dk...
Quote:
""Thomas Mang"" <nospam (AT) nospam (DOT) ucar.edu> wrote in message
news:4220f20a$0$12126$3b214f66 (AT) usenet (DOT) univie.ac.at...
|
| ""Thorsten Ottosen"" <nesotto (AT) cs (DOT) auc.dk> schrieb im Newsbeitrag

| > the standard is going to change on this matter; the lates from the
October
| > meeting says that

| I don't get this. First, I was shocked when I read that modifications.
Now I
| have the hope I am simply misunderstanding what it means.
|
| Could you please provide real-world examples what an empty lvalue etc.
is,
| and how it is intended to be used?

int* p = 0;
..
int& r = *p;
..
if( &r != 0 )
{
r = 5;
}


Sorry for answering late.

What on earth is the usefullness of null-references?

Until now, references were great. It means you had an object. Say you write
a function that takes a reference - pretty common. The ones who called the
function knew they had to provide an object, the ones who wrote the function
implementation knew they got an object. If the object is not obligatory, you
simply provide an overload for that function. Simple, clear, straightforward
for the user and the implementor.
Now it seems null-references break this. It breaks the contract for
functions (everyone wants to pass in a null-reference now too and expect
defined behavior), it breaks the implementation that counts on a "non-null
reference".
What am I supposed to do? The quick and dirty solution is to document
somewhere whereever a reference is used, a valid object has to be provided.
The clean solution is to document for each and every parameter it must not
be a null reference, and of course inside the implementation an assert is
done it is indeed not a null-reference. That seems to be quite a lot of
work.

So what I am interested in is: What do the people wanting to get this into
C++0x gain? I see a lot to lose, I see lots of time wasted to modify existin
g code base to make it "compatible"/error resistant to this strange new
thing, but nothing to gain. Thus I don't like the idea at all (to put it
politely).
What are null-references supposed to do other than being a plague?


Thomas


---
[ 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 ]


Back to top
Falk Tannhäuser
Guest





PostPosted: Thu Mar 10, 2005 11:24 pm    Post subject: Re: How to avoid null references ? Reply with quote

Thomas Mang wrote:
Quote:
What on earth is the usefullness of null-references?

I fully agree with your objections.
I followed the link posted in this thread by Marc Schoolderman on March 7
<http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#453> and in
my understanding, while the concept of "empty lvalues" is introduced to
clarify some consistency issues in the Standard, it will FORTUNATELY remain
illegal to bind such empty lvalues (in particular, dereferenced NULL pointers)
to references. So we can continue to sleep well...
However, binding references to not-yet-initialised objects is and remains
allowed, provided one doesn't do too much things which such a reference until
the initialisation completed.

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 ]


Back to top
Thorsten Ottosen
Guest





PostPosted: Thu Mar 10, 2005 11:54 pm    Post subject: Re: How to avoid null references ? Reply with quote

""Thomas Mang"" <nospam (AT) nospam (DOT) ucar.edu> wrote


Quote:
Sorry for answering late.

What on earth is the usefullness of null-references?

well, you can say something like

vector<int> foo;
..
int* end = &*end();

instead of

int* end = &*begin() + foo.size();

I think, but I don't know for sure, that the motivation
was to make this and similar cases well-defined. With a new for loop, you
might want to say

for( int& f : foo | indirect )
if( &f )
f += 2;

instead of

for( int* f : foo )
if( f )
*f += 2;

Anyway, I think the general rule that says I can rely on a
reference argument to be valid is good; the caller should
check that the pointer is valid before dereferencing.

-Thorsten


---
[ 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 ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ language, library and standards All times are GMT
Goto page 1, 2, 3  Next
Page 1 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.