Is this code snippet undefined behavior?

Discussion in 'C++' started by davidg@kixeye.com, Aug 22, 2012.

  1. Guest

    class A
    {
    public:
    A(int x);
    ...
    Amethod();
    };

    class B
    {
    public:
    B() : a_ref(a), a(42) { }
    ...
    Bmethod() { a_ref.Amethod(); }
    ...
    private:
    A &a_ref;
    A a;
    };

    Since the standard states that initializers are executed in the order given in the class definition, this means a_ref is initialized before a, and yet a_ref is trying to reference a.

    The reason I ask is that I found the same pattern in the source to the latest Mongodb C++ drivers, and when compiled with GCC it will sometimes wind up leaving a_ref referencing a NULL pointer.

    What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I single step from B::Bmethod() into A::Amethod() and inspect "this", it's NULL.
    , Aug 22, 2012
    #1
    1. Advertising

  2. On 8/22/2012 4:25 PM, wrote:
    > class A
    > {
    > public:
    > A(int x);
    > ...
    > Amethod();
    > };
    >
    > class B
    > {
    > public:
    > B() : a_ref(a), a(42) { }
    > ...
    > Bmethod() { a_ref.Amethod(); }
    > ...
    > private:
    > A &a_ref;
    > A a;
    > };
    >
    > Since the standard states that initializers are executed in the
    > order given in the class definition, this means a_ref is initialized
    > before a, and yet a_ref is trying to reference a.


    Not sure what you mean by "yet a_ref is trying to reference a". The
    initialization of a reference does not need the value, it does not touch
    the value. Essentially it makes sure that when you use 'a_ref'
    variable, it will be *as if* you actually used 'a', that's all
    *references* are for.

    The *object* designated by the 'a' member is not initialized until after
    a reference to it is obtained. Undefined behavior? Not sure. I think
    it's implementation-defined, but doesn't have to be documented.

    > The reason I ask is that I found the same pattern in the source to
    > the latest Mongodb C++ drivers, and when compiled with GCC it will
    > sometimes wind up leaving a_ref referencing a NULL pointer.


    You seem to be saying that GCC implements references as pointers, gives
    them storage, and in this particular case using 'a_ref' is like
    dereferencing a null pointer because it's initialized with an object
    that itself hasn't been initialized. <shrug> So?
    Implementation-defined, just like all references.

    > What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I
    > single step from B::Bmethod() into A::Amethod() and inspect "this",
    > it's NULL.


    That's a QoI issue, I believe. And my opinion of GCC's QoI is not very
    high.

    Some other compiler *may* do it differently. Although the 'a' object
    has not been initialized, the *storage* for it has already been
    allocated, and, if your references are pointers behind the scenes, you
    can figure out the address of 'a' and initialize 'a_ref' with it even
    though the storage itself hasn't been properly run through a constructor
    yet. QoI.

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Aug 22, 2012
    #2
    1. Advertising

  3. wrote:
    > Since the standard states that initializers are executed in the
    > order given in the class definition, this means a_ref is initialized
    > before a, and yet a_ref is trying to reference a.


    Dereferencing an uninitialized object is UB. I don't see any reason why
    referencing one would be.
    Juha Nieminen, Aug 23, 2012
    #3
  4. Gil Guest

    On Aug 22, 4:25 pm, wrote:
    > class A
    > {
    > public:
    >     A(int x);
    >     ...
    >     Amethod();
    >
    > };
    >
    > class B
    > {
    > public:
    >     B() : a_ref(a), a(42) { }
    >     ...
    >     Bmethod() { a_ref.Amethod(); }
    >     ...
    > private:
    >     A &a_ref;
    >     A a;
    >
    > };
    >
    > Since the standard states that initializers are executed in the order given in the class definition, this means a_ref is initialized before a, and yet a_ref is trying to reference a.
    >
    > The reason I ask is that I found the same pattern in the source to the latest Mongodb C++ drivers, and when compiled with GCC it will sometimes windup leaving a_ref referencing a NULL pointer.
    >
    > What I mean by that is when B::Bmethod calls a_ref.Amethod(), if I singlestep from B::Bmethod() into A::Amethod() and inspect "this", it's NULL.


    it is well formed in your example as per [basic.life]; note that if
    for example you'd try
    something like

    B() : a_ref( a.i_ ), a(42) { }

    where a_ref would be a int reference and class A still non pod - this
    time it would be UB.
    read [basic.life]/6 and [class.cdtor]/1,2

    hth,
    gil
    Gil, Aug 23, 2012
    #4
    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. Clare Hsiao
    Replies:
    0
    Views:
    319
    Clare Hsiao
    Feb 12, 2004
  2. Tom
    Replies:
    3
    Views:
    413
    Jeffrey Palermo [MCP]
    Dec 1, 2004
  3. Mantorok Redgormor
    Replies:
    70
    Views:
    1,734
    Dan Pop
    Feb 17, 2004
  4. Chris Thomasson
    Replies:
    10
    Views:
    548
    Alf P. Steinbach
    Nov 17, 2006
  5. Wake up Brazil
    Replies:
    10
    Views:
    111
    Öö Tiib
    Apr 16, 2014
Loading...

Share This Page