This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Lifetime bug in temporaries


// I've got a problem with the lifetime of temporaries. Since the
// corresponding code is short enough, I can post it:

#include <stdlib.h>
#include <iostream>

const size_t SIZE=50;

template<class U>class Expr
   {
   const U &a;
public:
   typedef typename U::value_type value_type;
   Expr(const U &x): a(x) 
      { 
      cout << "Expr[0] = " << a[0] << endl;
      }
value_type operator[](size_t i) const
      {
      return a[i];
      }
   };


template<class U, class V>
class SumExpr
   {
   typedef typename V::value_type value_type;
   const U &a;
   const V &b;
public:
   value_type operator[](size_t i) const
      {
      return a[i] + b[i];
      }
   SumExpr(const U &x, const V &y): a(x), b(y) 
      {
      cout << "Sum[0] = " << a[0] << "+" << b[0] << endl;
      }
   };

template<class T>class Vector
   {
   typedef T value_type;
   value_type value[SIZE];
public:
   value_type operator[](size_t i) const
      {
      return value[i];
      }

   value_type& operator[](size_t i)
      {
      return value[i];
      }

   template<class U>Vector &operator=(const Expr<U>& e)
      {
      for (size_t i = 0; i < SIZE; i++)
         value[i] = e[i];
      return *this;
      }
   };

template<class U>Expr<U> make_expr(const U &v)
   {
   return Expr<U>(v);
   }

template<class U, class V>SumExpr<U, V>make_sum(const U &a, const V &b)
   {
   return SumExpr<U, V>(a, b);
   }


template<class U, class V>inline Expr<SumExpr<Vector<U>, Vector<V> > >
operator+(const Vector<U> &a, const Vector<V> &b)
   {
   return make_expr(make_sum(a, b));
   }

int main()
   {
   Vector<double> a, b, c;
   
   for (size_t i = 0; i < SIZE; i++)
      {
      a[i] = 2;
      b[i] = 3;
      c[i] = i;
      }

   Vector<double> d;

   d = a+b;

   for (size_t i = 0; i < SIZE; i++)
      cout << d[i] << " ";
   cout << endl;
   }

/*
for those of you familiar with Blitz++, this should appear
as evident.

However, it crashes (SEGV) with a cvs-current egcs, compiled with 
enabled-haifa, on either dec-osf or solaris.

I've investigated it further with gdb-4.16.85.
The crash occurs in SumExpr<..>::operator[]()
It appears that b has been overwritten with a 0.
Setting up a watchpoint, it appears that the overwriting occurs
in 
	for (size_t i = 0; i < SIZE; i++)
(in Vector::operator=)
Apparently, the compiler uses the same location for my temporary
as per i. Indeed, if I declare i to be static, everything works fine.

My understanding though, is that the SumExpr<..>  temporary should
still be alive at this point.

Am I missing something, or is g++ lifetime of temporaries still not in
tune with what it should be ?
*/


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]