When a structure is defined without a constructor but that contains non-pod
data, the containing structure is also non-pod. When an array of these
enclosing non-pod structures is declared as a global static array with an
initializer list, the structures appear to be constructed on the stack and
copied into place without the use of the copy constructors of the contained
non-pod members, which is illegal.

The following C++ program demonstrates the problem:

#include <iostream>

class A {
public:
  A( int b ) {
    a_ = reinterpret_cast< void * >( this );
    b_ = b;
  }
  A( A const & that ) {
    a_ = this;
    b_ = that.b_;
  }

  void dump() const {
    std::cout << "  this = " << reinterpret_cast< const void * >( this ) <<
std::endl;
    std::cout << "  a_ = " << a_ << std::endl;
    std::cout << "  b_ = " << b_ << std::endl << std::endl;
  }

private:
  const void * a_;
  int b_;
};

A globalA( 1 );

static const A globalAArray[] =
{
  A( 11 ),
  A( 22 ),
  A( 33 )
};

struct ContainsA {
#if !defined( SHOW_GCC_BUG )
  ContainsA( A const & a1, A const & a2 );
#endif  // #if !defined( SHOW_GCC_BUG )
  A a1_;
  A a2_;
};
#if !defined( SHOW_GCC_BUG )
ContainsA::ContainsA( A const & a1, A const & a2 )
  : a1_( a1 ),
    a2_( a2 ) {
}
#endif  // #if !defined( SHOW_GCC_BUG )

static const ContainsA containsAArray[] =
{
#if !defined( SHOW_GCC_BUG )
  ContainsA( A( 111 ), A( 222 ) ),
  ContainsA( A( 333 ), A( 444 ) ),
  ContainsA( A( 555 ), A( 666 ) )
#else  // #if !defined( SHOW_GCC_BUG )
  {
    A( 111 ),
    A( 222 )
  },
  {
    A( 333 ),
    A( 444 )
  },
  {
    A( 555 ),
    A( 666 )
  }
#endif  // #if !defined( SHOW_GCC_BUG )
};


int main( void ) {
  std::cout << "Global A:" << std::endl;
  globalA.dump();

  std::cout << "Local A:" << std::endl;
  A localA( 3 );
  localA.dump();

  std::cout << "Global A Array:" << std::endl;
  for ( int i = 0; i < 3; ++i ) {
    globalAArray[ i ].dump();
  }

  std::cout << "Global ContainsA Array:" << std::endl;
  for ( int i = 0; i < 3; ++i ) {
    containsAArray[ i ].a1_.dump();
    containsAArray[ i ].a2_.dump();
  }

  return 0;
}

If this program is compiled (on gcc 3.4.2) using -DSHOW_GCC_BUG and run, the
output shows that "a_ != this", which is not correct. Both constructors of the
non-pod A class assign "a_ = this". There should never be an instance of A
where "a_ != this". Inspecting the values of a_ when "a_ != this" shows that
they are similar to the value of a_ for the instance of class A created locally
(on the stack), suggesting that the instances of A or the instances of
ContainsA were created on the stack and then memcpy'd or memmov'd into place
rather than copy constructed into place. Either of these cases is invalid
because class A is non-pod and should not ever be memcpy'd.


-- 
           Summary: Non-pod data structure copied incorrectly during static
                    initialization
           Product: gcc
           Version: 3.4.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: e_hohenstein at yahoo dot com


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26862

Reply via email to