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 

Dereferencing a null-pointer allowed?
Goto page 1, 2  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
Lutz Richter
Guest





PostPosted: Tue May 08, 2007 10:53 pm    Post subject: Dereferencing a null-pointer allowed? Reply with quote



Hi,

given the following code:

-----------------------------
class B
{
public:
B(): Value(99) {}
int Get() { if (this) return Value; else return -1; }

private:
int Value;
};

int main()
{
B* b = 0;
cout << b->Get();
}
-----------------------------


I wonder if this is allowed. I did not have any problem with any
compiler yet. It works! But is this guaranteed?

Unfortunately Stroustrop & Co. do not mention this problem in their
books. If anyone has a documentation about NOT doing the above example,
then please tell me.

Thanks in advance, Lutz.

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Hyman Rosen
Guest





PostPosted: Tue May 08, 2007 10:53 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote



Lutz Richter wrote:
Quote:
int Get() { if (this) return Value; else return -1; }

This is legal, but a good compiler will elide the test and
assume that 'this' is always non-null.

Quote:
B* b = 0; cout << b->Get();

This is undefined behavior, because you may not indirect
through a null pointer.

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Daniel Krügler
Guest





PostPosted: Tue May 08, 2007 10:53 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote



Quote:
I wonder if this is allowed. I did not have any problem with any
compiler yet. It works! But is this guaranteed?

Unfortunately Stroustrop & Co. do not mention this problem in their
books. If anyone has a documentation about NOT doing the above example,
then please tell me.

As Hyman Rosen explained, it causes UB, what you do above.
Since you asked additionally for a reference, here we go:

1.9/4:
"Certain other operations are described in this International Standard
as
undefined (for example, the effect of dereferencing the null pointer).
[..]"

5.2.5/3:
"If E1 has the type "pointer to class X," then the expression E1->E2
is
converted to the equivalent form (*(E1)).E2;[..]"

5.3.1/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.[..]"

8.3.2/4:
"[..] Note: in particular, 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,
which causes undefined behavior."

So yes, the essence is rather distributed among the standard, but
it is clearly expressed that you cannot use the dereferenced result
of an object pointer to access its members.

Greetings from Bremen,

Daniel Krügler



---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
James Kanze
Guest





PostPosted: Thu May 10, 2007 4:56 am    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

===================================== MODERATOR'S COMMENT:

(Apologies for this comment, which is present to bypass broken
spam filtering implemented by Cox.)


===================================== END OF MODERATOR'S COMMENT
On May 8, 11:03 pm, Daniel Krügler <daniel.krueg...@googlemail.com>
wrote:
Quote:
So yes, the essence is rather distributed among the standard, but
it is clearly expressed that you cannot use the dereferenced result
of an object pointer to access its members.

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Marco Manfredini
Guest





PostPosted: Thu May 10, 2007 8:56 am    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

===================================== MODERATOR'S COMMENT:

(Apologies for this comment, which is present to bypass broken
spam filtering implemented by Cox.)


===================================== END OF MODERATOR'S COMMENT
Daniel Krügler wrote:

Quote:
5.3.1/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.[..]"

8.3.2/4:
"[..] Note: in particular, 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,
which causes undefined behavior."

So yes, the essence is rather distributed among the standard, but
it is clearly expressed that you cannot use the dereferenced result
of an object pointer to access its members.

lvalues are not references - The same paragraph says, that you can not
form a reference to a bit field member, but bit fields members make
perfect lvalues.

Marco

--
// MUST be set to 1!
Params->ParentalLevel = 3; // QA now insist this is set to 2.


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Daniel Krügler
Guest





PostPosted: Thu May 10, 2007 12:23 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

===================================== MODERATOR'S COMMENT:



===================================== END OF MODERATOR'S COMMENT
On May 10, 6:56 am, James Kanze <james.ka...@gmail.com> wrote:
Quote:
On May 8, 11:03 pm, Daniel Krügler <daniel.krueg...@googlemail.com
wrote:

So yes, the essence is rather distributed among the standard, but
it is clearly expressed that you cannot use the dereferenced result
of an object pointer to access its members.

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

I tried to exclude your example by saying "cannot use".
I meant "use" here in the way defined by 3.2/2:

"An expression is potentially evaluated unless it appears
where an integral constant expression is required (see 5.19),
is the operand of the sizeof operator (5.3.3), or is the
operand of the typeid operator and the expression does not
designate an lvalue of polymorphic class type (5.2.Cool.
An object or non-overloaded function is used if its name
appears in a potentially-evaluated expression."

Obviously my wording was not unmistakably, so thanks
for this point, James!

Greetings,

Daniel


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Daniel Krügler
Guest





PostPosted: Thu May 10, 2007 12:23 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

===================================== MODERATOR'S COMMENT:



===================================== END OF MODERATOR'S COMMENT
Quote:
Daniel Krügler wrote:
5.3.1/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.[..]"

8.3.2/4:
"[..] Note: in particular, 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,
which causes undefined behavior."

So yes, the essence is rather distributed among the standard, but
it is clearly expressed that you cannot use the dereferenced result
of an object pointer to access its members.

lvalues are not references - The same paragraph says, that you can not
form a reference to a bit field member, but bit fields members make
perfect lvalues.

I did not claim anything in the way you interpret it
here and I also did not relate that to lvalues, I just
quoted the note of 8.3.2/4, because it argues that
the act of creating a null reference would imply to
bind it to the "object" obtained by dereferencing
a null pointer. The last point is relevant for this
discussion, nothing more.

Greetings from Bremen,

Daniel Krügler


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Ron Natalie
Guest





PostPosted: Thu May 10, 2007 1:06 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

===================================== MODERATOR'S COMMENT:



===================================== END OF MODERATOR'S COMMENT
James Kanze wrote:

Quote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

Correct, sizeof doesn't evaluate it's argument, it merely

checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Greg Herlihy
Guest





PostPosted: Thu May 10, 2007 5:26 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

On May 10, 6:06 am, Ron Natalie <r...@spamcop.net> wrote:
Quote:
James Kanze wrote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

Correct, sizeof doesn't evaluate it's argument, it merely
checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

Nonetheless, dereferencing a null pointer in a typeid expression has
well-defined behavior - the result is a thrown bad_typeid exception,
per §5.2.8/2.

Greg


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
James Dennett
Guest





PostPosted: Fri May 11, 2007 9:11 am    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

Greg Herlihy wrote:
Quote:
On May 10, 6:06 am, Ron Natalie <r...@spamcop.net> wrote:
James Kanze wrote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.
Correct, sizeof doesn't evaluate it's argument, it merely
checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

Nonetheless, dereferencing a null pointer in a typeid expression has
well-defined behavior - the result is a thrown bad_typeid exception,
per §5.2.8/2.

I don't think that can be right; at least not without
qualification. typeid(*expr) is well-defined even if
expr is a null pointer, but if expr itself includes
a dereference operation on a null pointer (and the
typeid requires runtime evaluation) then the behavior
can still be undefined, just as if expr were evaluated
in any other context.

-- James

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
James Kanze
Guest





PostPosted: Fri May 11, 2007 5:37 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

On May 10, 7:26 pm, Greg Herlihy <gre...@pacbell.net> wrote:
Quote:
On May 10, 6:06 am, Ron Natalie <r...@spamcop.net> wrote:
James Kanze wrote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

Correct, sizeof doesn't evaluate it's argument, it merely
checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

Nonetheless, dereferencing a null pointer in a typeid expression has
well-defined behavior - the result is a thrown bad_typeid exception,
per §5.2.8/2.

No. The only case that happens is if the argument to typeid is
an lvalue expression which "is obtained by applying * to a
pointer". In an example such at the above (replacing sizeof
with typeid), if the return type of T::f() is anything but a
reference to a polymorphique type, the expression is not
evaluated, at all. If the return type is a reference to a
polymorphic object, then the expression is evaluated, and we get
undefined behavior (probably a core dump if T::f() is virtual,
or uses the contents of the class in any way).

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
W Karas
Guest





PostPosted: Fri May 11, 2007 9:13 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

On May 8, 1:53 pm, l...@gmx.li (Lutz Richter) wrote:
Quote:
Hi,

given the following code:

-----------------------------
class B
{
public:
B(): Value(99) {}
int Get() { if (this) return Value; else return -1; }

private:
int Value;

};

int main()
{
B* b = 0;
cout << b->Get();}

-----------------------------

I wonder if this is allowed. I did not have any problem with any
compiler yet. It works! But is this guaranteed?

Unfortunately Stroustrop & Co. do not mention this problem in their
books. If anyone has a documentation about NOT doing the above example,
then please tell me.

Thanks in advance, Lutz.

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

(Resend this, my apologies if it is a duplicate)

This question touches on a broader issue: the C++ Standard is often
much more
strict than the de facto standard that can be inferred from the widely-
used C++
implementations.

I would guess that the above code would compile and run properly with
any
widely-used C++ compiler. To me personally, it would be much more
intuitive to do this kind of a test for null in a static class member
function
that took an instance pointer as an explicit parameter. So that
might be why the Standard is stricter in this case.

A more complicated case is the restrictions on memcpy-ing
objects to/from arrays of char. In de facto C++, this works fine
for objects of primitive type or any class with a valid default copy
constructor whose data members and base classes are
also memcpy-able. Standard C++ restricts memcpy-ing to
POD types. This has some advantages if the Standard
will someday use the concept of memcpy-ability to venture
into the untouched territories of binary secondary storage
and transfers in shared memory. But even then, the restriction
to POD only seems overly strict.

On the other hand, de facto C++ (in order to avoid
breaking old C code I would guess) can be restrictive
in perhaps undesirable ways. For example, if I write:

class X { char a; int i; char b; };

I've not seen any compilers that would store b
before i in the structure, even though this seems
to be ok under the Standard (?), although it
perhaps shouldn't be for POD.

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
James Kanze
Guest





PostPosted: Sat May 12, 2007 10:47 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

On May 11, 11:13 pm, W Karas <wka...@yahoo.com> wrote:
Quote:
On May 8, 1:53 pm, l...@gmx.li (Lutz Richter) wrote:
given the following code:

-----------------------------
class B
{
public:
B(): Value(99) {}
int Get() { if (this) return Value; else return -1; }

private:
int Value;

};

int main()
{
B* b = 0;
cout << b->Get();}

-----------------------------

I wonder if this is allowed. I did not have any problem with any
compiler yet. It works! But is this guaranteed?

This question touches on a broader issue: the C++ Standard is
often much more strict than the de facto standard that can be
inferred from the widely- used C++ implementations.

That's partially true. Sometimes, it is because C++ tries to
remain implementable on more exotic architectures. Thus, you
will have no problems on most common architectures copying a
pointer after it has been used as the operand to delete, but
there are some exotic (and in the past not so exotic)
architectures where this might be more difficult to implement,
so C++ declares it undefined behavior. In other cases, the
standard's committee does end up standardizing existing
practice, once it becomes clear that it really is universal: the
next version of the standard will require the memory in
std::string to be contiguous, for example, and that <iostream>
actually include <istream>, <ostream>, etc. (When the last
version of the standard was adopted, no one had sufficient
experience with these issues to be sure that there might not be
cases where it was reasonable to do otherwise. Time has shown,
however, that there aren't.)

Quote:
I would guess that the above code would compile and run
properly with any widely-used C++ compiler.

Unless, of course, the compiler was serious about optimization.
I can't imagine it running "correctly" (assuming that outputting
-1 is "correct") with any decent optimization. And of course,
even on compilers where it currently runs "correctly", it is
just a special case. Throw in multiple inheritance or virtual
functions, and it will do strange things with a lot of
compilers.

Quote:
On the other hand, de facto C++ (in order to avoid
breaking old C code I would guess) can be restrictive
in perhaps undesirable ways. For example, if I write:

class X { char a; int i; char b; };

I've not seen any compilers that would store b
before i in the structure, even though this seems
to be ok under the Standard (?), although it
perhaps shouldn't be for POD.

It's forbidden. I think there is a DR concerning this, however.
Formally:

struct A { char a; int i; char b; } ;
// Order guaranteed.
struct B { public: char a; public: int i; public: char b; } ;
// Order not guaranteed.

In the latter case, however, B is still a POD.
--
James Kanze (Gabi Software) email: james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
Ron Natalie
Guest





PostPosted: Sat May 12, 2007 10:47 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

Greg Herlihy wrote:
Quote:
On May 10, 6:06 am, Ron Natalie <r...@spamcop.net> wrote:
James Kanze wrote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.
Correct, sizeof doesn't evaluate it's argument, it merely
checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

Nonetheless, dereferencing a null pointer in a typeid expression has
well-defined behavior - the result is a thrown bad_typeid exception,
per §5.2.8/2.

Sort of...


That clause applies to something like this:
T* tp = 0;

typeid *tp;

Int he case of the expression written originally (substituting
typeid for sizeof) it's still undefined behavior.

---
[ 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.comeaucomputing.com/csc/faq.html ]
Back to top
James Kanze
Guest





PostPosted: Sun May 13, 2007 3:48 pm    Post subject: Re: Dereferencing a null-pointer allowed? Reply with quote

On May 10, 3:06 pm, Ron Natalie <r...@spamcop.net> wrote:
Quote:
James Kanze wrote:

With one important exception, I believe: if the expression is
used as an argument to sizeof or typeid. Something like:
sizeof( ((T*)0)->f() )
is legal, I think.

Correct, sizeof doesn't evaluate it's argument, it merely
checks the type.

Typeid does however potentially do so, since the result
may be something it has to test the dynamic typing of.

Good point. But if I understand §5.2.8 correctly, this can only
happen in a case like the above if the return value is a
reference to a type having at least one virtual function. (Of
course, if I know the type, and it cannot be polymorphic, what's
the point of using typeid?) It's interesting to note that this
depends only on the return type of T::f()---whether T::f() is
virtual or not plays no role in the issue.

--
James Kanze (GABI Software) email:james.kanze (AT) gmail (DOT) com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


---
[ 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.comeaucomputing.com/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  Next
Page 1 of 2

 
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.