passing null as parameter to reference to an object

S

shaan

I have following function:
void myfunction (int &a , bool g )
{
if(g)
{
int k = a;
}
}


int main()
{
int * ptr = NULL;
myfunction(*ptr, false);

}

Is passing null to a reference legal? What standard has to say about this ?
 
V

Victor Bazarov

I have following function:
void myfunction (int &a , bool g )
{
if(g)
{
int k = a;
}
}


int main()
{
int * ptr = NULL;
myfunction(*ptr, false);

}

Is passing null to a reference legal? What standard has to say about this ?

You're dereferencing a null pointer, and that has undefined behavior
(read up on that). Not illegal, just not defined at all. It might do
what you expect (like crash the program due to invalid memory access),
or it might e-mail dirty pictures of your grandma to the Deputy Prime
Minister.

V
 
W

Wouter van Ooijen

Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined behavior
(read up on that). Not illegal, just not defined at all. It might do
what you expect (like crash the program due to invalid memory access),
or it might e-mail dirty pictures of your grandma to the Deputy Prime
Minister.

Note that in this example, g is false, hence at run time the integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Wouter
 
V

Victor Bazarov

Victor Bazarov schreef op 23-Dec-13 1:40 PM:

Note that in this example, g is false, hence at run time the integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant quoting,
please.

V
 
W

Wouter van Ooijen

Victor Bazarov schreef op 23-Dec-13 2:06 PM:
Expression *ptr _is_ dereferencing. And don't remove relevant quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

Wouter
 
M

Marcel Müller

Am 23.12.2013 11:51, schrieb shaan:
int main()
{
int * ptr = NULL;
myfunction(*ptr, false);
}

Is passing null to a reference legal? What standard has to say about this ?

As mentioned this is undefined behavior. But not only in theory.
The following example will typically fail on many implementations:

class A
{};

class B
{};

class C : public A, public B
{};

void foo(C& c)
{ B& b = c;
B* bp = &b;
// now bp is a non NULL pointer!
}

int main()
{ C* cp = NULL;
foo(*cp);
}

Because C++ references must not be NULL the compiler dropped the code to
skip the the pointer adjustment for the multiple inheritance in case of
NULL. So the value of bp is typically 0x04 although a NULL pointer has
been passed. Of course, this is implementation dependant.


Marcel
 
V

Victor Bazarov

Victor Bazarov schreef op 23-Dec-13 2:06 PM:
Expression *ptr _is_ dereferencing. And don't remove relevant quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V
 
W

Wouter van Ooijen

Victor Bazarov schreef op 23-Dec-13 3:18 PM:
Victor Bazarov schreef op 23-Dec-13 2:06 PM:
On 12/23/2013 7:57 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined behavior
(read up on that). Not illegal, just not defined at all. It might do
what you expect (like crash the program due to invalid memory access),
or it might e-mail dirty pictures of your grandma to the Deputy Prime
Minister.

Note that in this example, g is false, hence at run time the integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V

Follows where? not in 5.3.1-4, which is what follows my quote.

And where is the lvalue-to-rvalue conversion in the code example that
Shaan posted?

W
 
V

Victor Bazarov

Victor Bazarov schreef op 23-Dec-13 3:18 PM:
Victor Bazarov schreef op 23-Dec-13 2:06 PM:
On 12/23/2013 7:57 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined behavior
(read up on that). Not illegal, just not defined at all. It
might do
what you expect (like crash the program due to invalid memory
access),
or it might e-mail dirty pictures of your grandma to the Deputy Prime
Minister.

Note that in this example, g is false, hence at run time the
integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V

Follows where? not in 5.3.1-4, which is what follows my quote.

And where is the lvalue-to-rvalue conversion in the code example that
Shaan posted?

The *ptr is an lvalue. The argument is a const ref, which only binds to
an rvalue. So, you quoted the Standard about the *ptr, I am suggesting
that lvalue-to-rvalue conversion takes place at the time of the call to
the function. That follows the *ptr evaluation.

V
 
W

Wouter van Ooijen

Victor Bazarov schreef op 23-Dec-13 5:01 PM:
Victor Bazarov schreef op 23-Dec-13 3:18 PM:
On 12/23/2013 8:33 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 2:06 PM:
On 12/23/2013 7:57 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined behavior
(read up on that). Not illegal, just not defined at all. It
might do
what you expect (like crash the program due to invalid memory
access),
or it might e-mail dirty pictures of your grandma to the Deputy
Prime
Minister.

Note that in this example, g is false, hence at run time the
integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant
quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V

Follows where? not in 5.3.1-4, which is what follows my quote.

And where is the lvalue-to-rvalue conversion in the code example that
Shaan posted?

The *ptr is an lvalue. The argument is a const ref, which only binds to
an rvalue. So, you quoted the Standard about the *ptr, I am suggesting
that lvalue-to-rvalue conversion takes place at the time of the call to
the function. That follows the *ptr evaluation.

V

The argument is an 'int &' , nothing const about that, so IMO no need
for conversion to rvalue. At the call the *ptr is bound to an 'int &',
nothing more, and that is exactly what 5.3.1-3 allows.

Wouter
 
S

Seungbeom Kim

Quoting 5.3.1:
[...] 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. [...]

Did the empty lvalue proposal officially make it to the standard?
I see the proposed resolutions from CWG issue #232[1], but not the
relevant parts in later working drafts, such as N3485[2] or N3797[3].

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf
[3] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf
 
W

Wouter van Ooijen

Seungbeom Kim schreef op 23-Dec-13 8:10 PM:
Quoting 5.3.1:
[...] 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. [...]

Did the empty lvalue proposal officially make it to the standard?
I see the proposed resolutions from CWG issue #232[1], but not the
relevant parts in later working drafts, such as N3485[2] or N3797[3].

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf
[3] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

I got it from
http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents
where it is described as "2012-01-16: N3337 Essentially C++11 with minor
errors and typos corrected"

Wouter
 
V

Victor Bazarov

Victor Bazarov schreef op 23-Dec-13 5:01 PM:
Victor Bazarov schreef op 23-Dec-13 3:18 PM:
On 12/23/2013 8:33 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 2:06 PM:
On 12/23/2013 7:57 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined
behavior
(read up on that). Not illegal, just not defined at all. It
might do
what you expect (like crash the program due to invalid memory
access),
or it might e-mail dirty pictures of your grandma to the Deputy
Prime
Minister.

Note that in this example, g is false, hence at run time the
integer at
NULL is never accessed. Does the binding of a refernce to the object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant
quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V

Follows where? not in 5.3.1-4, which is what follows my quote.

And where is the lvalue-to-rvalue conversion in the code example that
Shaan posted?

The *ptr is an lvalue. The argument is a const ref, which only binds to
an rvalue. So, you quoted the Standard about the *ptr, I am suggesting
that lvalue-to-rvalue conversion takes place at the time of the call to
the function. That follows the *ptr evaluation.

V

The argument is an 'int &' , nothing const about that, so IMO no need
for conversion to rvalue. At the call the *ptr is bound to an 'int &',
nothing more, and that is exactly what 5.3.1-3 allows.

Oh, sorry then. I must have confused that code with some other code I
saw. My apology, will be paying more attention next time.

V
 
W

Wouter van Ooijen

Mr Flibble schreef op 23-Dec-13 8:26 PM:
Victor Bazarov schreef op 23-Dec-13 5:01 PM:
On 12/23/2013 10:07 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 3:18 PM:
On 12/23/2013 8:33 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 2:06 PM:
On 12/23/2013 7:57 AM, Wouter van Ooijen wrote:
Victor Bazarov schreef op 23-Dec-13 1:40 PM:
You're dereferencing a null pointer, and that has undefined
behavior
(read up on that). Not illegal, just not defined at all. It
might do
what you expect (like crash the program due to invalid memory
access),
or it might e-mail dirty pictures of your grandma to the Deputy
Prime
Minister.

Note that in this example, g is false, hence at run time the
integer at
NULL is never accessed. Does the binding of a refernce to the
object
pointed to realy counts as dereferencing?

Expression *ptr _is_ dereferencing. And don't remove relevant
quoting,
please.

Quoting 5.3.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]

Seems to me that this exactly covers the code eat hand.

It does, in part. Read on lvalue-to-rvalue conversion, which follows.

V

Follows where? not in 5.3.1-4, which is what follows my quote.

And where is the lvalue-to-rvalue conversion in the code example that
Shaan posted?

The *ptr is an lvalue. The argument is a const ref, which only binds to
an rvalue. So, you quoted the Standard about the *ptr, I am suggesting
that lvalue-to-rvalue conversion takes place at the time of the call to
the function. That follows the *ptr evaluation.

V

The argument is an 'int &' , nothing const about that, so IMO no need
for conversion to rvalue. At the call the *ptr is bound to an 'int &',
nothing more, and that is exactly what 5.3.1-3 allows.

It is UB, end of discussion.

/Flibble

You wishing it to be so is not a very convincing argument :)

Find the relevant quotes of the standard and you will convince me. As it
is now, the standard (in the passage that I quotes) explicitly allows it.

Wouter
 
A

Alf P. Steinbach

* Wouter van Ooijen:
* Mr Flibble a.k.a. "Sausage!":

You wishing it to be so is not a very convincing argument :)

Find the relevant quotes of the standard and you will convince me. As it
is now, the standard (in the passage that I quotes) explicitly allows it.

If this refers to whether the result of *p where p is a nullpointer, is
UB, well it /generally/ is UB.

But it's explicitly allowed as argument to typeid.

Also, many years ago there was some discussion about &*p and "one past
the array", due to some support in the C standard. I don't remember what
came of it. But C++11 tidied up the language about UB of dereferenced
nullpointer: in C++03 all one could find in the standard was a claim
that it was stated to be UB somewhere else (!) in the standard, while,
as I recall, in C++11 it's laid out more clearly.

Binding it to a reference is definitely over in UB-land.

As I recall that standard even explains things somewhere with the logic
that in a conforming program a reference can't be a nullreference.


Cheers & hth.,

- Alf (lazy mode, sorry)
 
S

Seungbeom Kim

Seungbeom Kim schreef op 23-Dec-13 8:10 PM:
Quoting 5.3.1:
[...] 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. [...]

Did the empty lvalue proposal officially make it to the standard?
I see the proposed resolutions from CWG issue #232[1], but not the
relevant parts in later working drafts, such as N3485[2] or N3797[3].

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#232
[2] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf
[3] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3797.pdf

I got it from http://stackoverflow.com/questions/81656/where-do-i-find-the-current-c-or-c-standard-documents
where it is described as "2012-01-16: N3337 Essentially C++11 with minor errors and typos corrected"

Thanks, but sorry, I don't see the quoted phrases in N3337 either;
the whole document doesn't seem to have the phrase "empty lvalue".
 
J

Jorgen Grahn

On Mon, 2013-12-23, Moreira David wrote:

[big snip]
And in some operating systems, the nullptr is a valid address and will
not make a segmentation fault.

Maybe from the operating system's point of view, but please note that
normal C or C++ code running on that system cannot easily use that
address for anything meaningful. E.g. you won't see 'new int' placing
that int object at address 0.

I've worked with a few systems like that, and you always look for
various ways of making null pointer dereferencing fail as noisily as
possible, because they /are/ invariably bugs.

/Jorgen
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,982
Messages
2,570,185
Members
46,738
Latest member
JinaMacvit

Latest Threads

Top