On Fri, 29 Apr 2011 12:32:24 -0700
Mike Stump <mikest...@comcast.net> wrote:

> On Apr 29, 2011, at 11:46 AM, Basile Starynkevitch wrote:
> > 
> > This bring me to a question. Does the C++ standard imply that this is
> > never a null pointer?
> 
> Does this:
> 
> 4 Certain other operations are described in this International  Standard
>   as  undefined  (for  example,  the  effect  of  dereferencing the null
>   pointer).  [Note: this International Standard imposes no  requirements
>   on the behavior of programs that contain undefined behavior.  ]
> 
> answer your question?  
Not really.

> Note, this is exactly the same as C.  You can't do it in C either:
> 
> struct A {
>   int x;
> } *pa = 0;
> 
> int main() {
>   pa->x = 1;
> }
> 
> If you run it, it will crash on all good OSes.  In C++, it will also crash.

The examples I gave did not crash, because they are non-virtual member
functions. I gave as example

>   class Myclass {
>      int x;
>    public:
>      Myclass(int z=0): x(z) {};
>      int get(void) const { if (this) return x; else return 0; };
>      ~Myclass() { };
>   };

Please notice that get above is a non-virtual member *function*

In the old days when C++ was a translator to C, the
generated C code would be something like

int Myclass__get (MyClass* this)
{ if (this) return this->x; else return 0; }

And such C code won't crash and is conforming to (old and current) C
standard[s].

My example did not dereference a null pointer! I did test some similar
code and on my Linux machine it did work as I expect.

So I still don't know if this can be null or not. After all, it is 
(in C++ parlance) a pointer, not a reference, and C++ pointers can be
null.

with gcc version 4.6.1 20110421 (prerelease) (Debian 4.6.0-5)
(Debian/Experimental on AMD64) the following file

/// file nullthis.cc
  class Myclass {
     int x;
   public:
     Myclass(int z=0): x(z) {};
     int get(void) const { if (this) return x; else return 0; };
     ~Myclass() { };
  };

extern "C" int myget (Myclass *c) { return c->get(); };
//// eof nullthis.cc

is compiled with g++ -Wall -O3 -fverbose-asm -S nullthis.cc
without warnings, and the only produced function in nullthis.s is
        .globl  myget
        .type   myget, @function
myget:
.LFB7:
        .cfi_startproc
        xorl    %eax, %eax      # D.2112
        testq   %rdi, %rdi      # c
        je      .L2     #,
        movl    (%rdi), %eax    # MEM[(const struct Myclass
*)c_1(D)].x, D.2112 .L2:
        rep
        ret
        .cfi_endproc
.LFE7:
        .size   myget, .-myget
        .ident  "GCC: (Debian 4.6.0-5) 4.6.1 20110421
(prerelease)"

This is exactly what I expect. But I don't know if it conforms to
standard.

When compiling with g++ -Wall -O3 -fdump-tree-all -fverbose-asm -S
nullthis.cc I have (among others) a dump file  
% cat nullthis.cc.131t.phiopt3                      

;; Function int myget(Myclass*) (myget)

int myget(Myclass*) (struct Myclass * c)
{
  int D.2112;

<bb 2>:
  if (c_1(D) != 0B)
    goto <bb 3>;
  else
    goto <bb 4>;

<bb 3>:
  D.2112_4 = MEM[(const struct Myclass *)c_1(D)].x;

<bb 4>:
  # D.2112_5 = PHI <0(2), D.2112_4(3)>
  return D.2112_5;

}
which is also what I expect. I have no idea if it is conforming to
standards. But I notice that the test about this is remaining in the
code. So apparently GCC 4.6 does not make the hypothesis that this is
never null, otherwise it would have optimized the test by removing it.
What I don't know (and I am asking) is if such an hypothetical
optimization is conforming to standards. My biased feeling is that it
is not (because I found no explicit & unambigous mention in standard
legal text that this is never null).

Of course, calling a virtual member function on null is obviously an
undefined behavior (and SIGSEGV under Linux).

Regards.
-- 
Basile STARYNKEVITCH         http://starynkevitch.net/Basile/
email: basile<at>starynkevitch<dot>net mobile: +33 6 8501 2359
8, rue de la Faiencerie, 92340 Bourg La Reine, France
*** opinions {are only mine, sont seulement les miennes} ***

Reply via email to