nullptr reference legal?

Discussion in 'C++' started by Jim Langston, Oct 23, 2010.

  1. Jim Langston

    Jim Langston Guest

    I wound up creating a null reference on accident using polymorphism and
    wondered if this snippet is legal code, as it compiles and works as I would
    expect it to work.

    void jglRenderModel( jglModel& model ) {
    if ( &model == nullptr ) {
    return;
    }
    /* ... */
    }

    // Following line may produce a nullptr reference
    jglRenderModel( *dynamic_cast<jmlGL::jglModel*>((world.objects.find(
    L"Cube" ))->second) );
    // Following line will produce a nullptr reference
    jglRenderModel( *reinterpret_cast<jmlGL::jglModel*>( nullptr ) );
     
    Jim Langston, Oct 23, 2010
    #1
    1. Advertising

  2. Jim Langston

    Jim Langston Guest

    "Jim Langston" <> wrote in message
    news:i9u4fj$35s$...
    >I wound up creating a null reference on accident using polymorphism and
    >wondered if this snippet is legal code, as it compiles and works as I would
    >expect it to work.
    >
    > void jglRenderModel( jglModel& model ) {
    > if ( &model == nullptr ) {
    > return;
    > }
    > /* ... */
    > }
    >
    > // Following line may produce a nullptr reference
    > jglRenderModel( *dynamic_cast<jmlGL::jglModel*>((world.objects.find(
    > L"Cube" ))->second) );
    > // Following line will produce a nullptr reference
    > jglRenderModel( *reinterpret_cast<jmlGL::jglModel*>( nullptr ) );


    Hmm.. this is dereferencing a nullptr isn't it? So I guess it's illegal.
    So I have to wrap the null reference around something just to do what I can
    already do. *sigh*
     
    Jim Langston, Oct 23, 2010
    #2
    1. Advertising

  3. Jim Langston wrote:
    > I wound up creating a null reference on accident using polymorphism and
    > wondered if this snippet is legal code, as it compiles and works as I
    > would expect it to work.
    >
    > void jglRenderModel( jglModel& model ) {
    > if ( &model == nullptr ) {
    > return;
    > }
    > /* ... */
    > }


    This code is valid. However, it makes no sense since &model must not be
    NULL.

    > // Following line may produce a nullptr reference
    > jglRenderModel( *dynamic_cast<jmlGL::jglModel*>((world.objects.find(
    > L"Cube" ))->second) );


    This code is invalid if and only if the dynamic cast returns nullptr
    since you must not dereference a nullptr.

    > // Following line will produce a nullptr reference
    > jglRenderModel( *reinterpret_cast<jmlGL::jglModel*>( nullptr ) );


    This code is always invalid.


    And no, these are not only restrictions of the language, it will really
    produce invalid machine code. The following example will behave
    unexpected on many platforms:

    struct A
    { int a;
    };
    struct B
    { int b;
    };
    struct C : public A, public B
    { int c;
    };

    C* cptr = NULL;
    C& cref = *cptr; // invalid, but usually here nothing strange happens
    B& bref = cref; // Now the nullptr turns into something not null.
    assert(&bref == NULL); // Fail!

    If a reference type conversion requires an adjustment of the offset, it
    is, in contrast to pointer types, not checked for NULL before. This
    implies also that the use of references instead of pointers that must
    not be NULL might have a performance gain with polymorphic types,
    because of the omitted NULL checks.


    Marcel
     
    Marcel Müller, Oct 23, 2010
    #3
  4. Jim Langston

    Bo Persson Guest

    Jim Langston wrote:
    > "Jim Langston" <> wrote in message
    > news:i9u4fj$35s$...
    >> I wound up creating a null reference on accident using
    >> polymorphism and wondered if this snippet is legal code, as it
    >> compiles and works as I would expect it to work.
    >>
    >> void jglRenderModel( jglModel& model ) {
    >> if ( &model == nullptr ) {
    >> return;
    >> }
    >> /* ... */
    >> }
    >>
    >> // Following line may produce a nullptr reference
    >> jglRenderModel(
    >> *dynamic_cast<jmlGL::jglModel*>((world.objects.find( L"Cube"
    >> ))->second) ); // Following line will produce a nullptr reference
    >> jglRenderModel( *reinterpret_cast<jmlGL::jglModel*>( nullptr ) );

    >
    > Hmm.. this is dereferencing a nullptr isn't it? So I guess it's
    > illegal. So I have to wrap the null reference around something just
    > to do what I can already do. *sigh*


    Right!

    We don't know of any way to create a "null reference" without first
    invoking undefined behavior.

    A rule of thumb is to make the parameter a pointer if you accept null
    values. Reference parameters are for when there must always be a valid
    object.


    Bo Persson
     
    Bo Persson, Oct 23, 2010
    #4
  5. Jim Langston

    Goran Pusic Guest

    On Oct 23, 9:56 am, "Jim Langston" <> wrote:
    > I wound up creating a null reference on accident using polymorphism and
    > wondered if this snippet is legal code, as it compiles and works as I would
    > expect it to work.
    >
    > void jglRenderModel( jglModel& model ) {
    >    if ( &model == nullptr ) {
    >       return;
    >    }


    Well, that's horrible code right there. It deals with passing an "null
    reference" in (in quotes, as there's no such thing as a "null
    reference" in C++). You can't have an invalid reference without
    another bug in your own code, so checking for it here is covering for
    a bug elsewhere, which is just wrong.

    I think you should either change your "model" param to a pointer,
    either make sure that you only go into jglRenderModel with a valid
    object.

    Goran.
     
    Goran Pusic, Oct 25, 2010
    #5
  6. Jim Langston

    Martin B. Guest

    On 23.10.2010 10:33, Marcel Müller wrote:
    > Jim Langston wrote:
    >> I wound up creating a null reference on accident using polymorphism
    >> and wondered if this snippet is legal code, as it compiles and works
    >> as I would expect it to work.
    >>
    >> [...]

    >
    >
    > And no, these are not only restrictions of the language, it will really
    > produce invalid machine code. The following example will behave
    > unexpected on many platforms:
    >
    > struct A
    > { int a;
    > };
    > struct B
    > { int b;
    > };
    > struct C : public A, public B
    > { int c;
    > };
    >
    > C* cptr = NULL;
    > C& cref = *cptr; // invalid, but usually here nothing strange happens
    > B& bref = cref; // Now the nullptr turns into something not null.
    > assert(&bref == NULL); // Fail!
    >
    > If a reference type conversion requires an adjustment of the offset, it
    > is, in contrast to pointer types, not checked for NULL before. This
    >[...]


    Who's checking when and what (part of the standard) mandates this behaviour?

    cheers,
    Martin
     
    Martin B., Oct 25, 2010
    #6
  7. Martin B. wrote:
    >> If a reference type conversion requires an adjustment of the offset, it
    >> is, in contrast to pointer types, not checked for NULL before. This
    >> [...]

    >
    > Who's checking when and what (part of the standard) mandates this
    > behaviour?


    The standard says absolutly nothing about that. But this is what is
    actually happening in implementations. In fact, I only like to show that
    NULL references are not just UB, but working as NULL pointers otherwise.
    They definitely break code.


    Marcel
     
    Marcel Müller, Oct 25, 2010
    #7
  8. On Oct 25, 11:16 am, "Martin B." <> wrote:
    > On 23.10.2010 10:33, Marcel Müller wrote:
    >
    >
    >
    > > Jim Langston wrote:
    > >> I wound up creating a null reference on accident using polymorphism
    > >> and wondered if this snippet is legal code, as it compiles and works
    > >> as I would expect it to work.

    >
    > >> [...]

    >
    > > And no, these are not only restrictions of the language, it will really
    > > produce invalid machine code. The following example will behave
    > > unexpected on many platforms:

    >
    > > struct A
    > > { int a;
    > > };
    > > struct B
    > > { int b;
    > > };
    > > struct C : public A, public B
    > > { int c;
    > > };

    >
    > > C* cptr = NULL;
    > > C& cref = *cptr; // invalid, but usually here nothing strange happens
    > > B& bref = cref; // Now the nullptr turns into something not null.
    > > assert(&bref == NULL); // Fail!

    >
    > > If a reference type conversion requires an adjustment of the offset, it
    > > is, in contrast to pointer types, not checked for NULL before. This
    > >[...]

    >
    > Who's checking when and what (part of the standard) mandates this behaviour?


    As derived to base conversions are not forbidden for null pointers and
    must yield a null pointer, this must work as expected:

    B* bptr = cptr;
    assert(bptr == NULL); // Pass

    If the conversion from C* to B* requires a pointer offset, that must
    be guarded to ensure that the result is still a nullpointer if the
    source was a null pointer.

    >
    > cheers,
    > Martin


    Bart v Ingen Schenau
     
    Bart van Ingen Schenau, Oct 26, 2010
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Valentin Tihomirov

    Is this legal?

    Valentin Tihomirov, Oct 21, 2003, in forum: VHDL
    Replies:
    20
    Views:
    1,258
    Jan Decaluwe
    Oct 29, 2003
  2. Divyang M
    Replies:
    9
    Views:
    639
    Divyang M
    May 18, 2005
  3. Replies:
    2
    Views:
    362
  4. Tom McGlynn

    Re: IllegalArg vs NullPtr Exceptions

    Tom McGlynn, Sep 30, 2009, in forum: Java
    Replies:
    5
    Views:
    344
    Mike Amling
    Oct 2, 2009
  5. Lynn McGuire

    nullptr is replacing NULL ?

    Lynn McGuire, Jul 8, 2011, in forum: C++
    Replies:
    4
    Views:
    4,432
    Lynn McGuire
    Jul 18, 2011
Loading...

Share This Page