Segfault that I can't explain

Started by
2 comments, last by MENTAL 17 years, 6 months ago
I made a small testcase of a weird problem I encountered in my code. In the following testcase:

template<typename T>
struct RGB
{
  T R;
  T G;
  T B;
  
  RGB() {}
  RGB(T R, T G, T B)
  {
    this->R = R;
    this->G = G;
    this->B = B;
  }
};

template<typename T>
RGB<T> operator+(const RGB<T>& a, const RGB<T>& b)
{
  RGB<T> result;
  result.R = a.R + b.R;
  result.G = a.G + b.G;
  result.B = a.B + b.B;
  return result;
}


#if 0
//this one causes no segfault
template<typename U, typename T>
struct alpha : public U
{
  T A; //alpha channel
  
  alpha() {}
  alpha(const U& in) { opaque() = in; }
  void operator=(const U& in) { opaque() = in; }

  private:
  U& opaque() { return *this; }
};

#else
//this one causes segfault
template<typename U, typename T>
struct alpha : public U
{
  T A; //alpha channel

  alpha() {}
  alpha(const U& in) { *this = in; }
  void operator=(const U& in) { *this = in; }
};

#endif

int main()
{
  RGB<int> a(128, 128, 128);
  RGB<int> b(64, 64, 64);
  RGB<int> c = a + b;
  
  alpha<RGB<int>, int> aa;
  alpha<RGB<int>, int> bb;
  alpha<RGB<int>, int> cc;
  
  aa = a;
  bb = b;
  cc = a + b;

  return 0;
}


there are two versions of the alpha struct. When using #if 1, the program will work correctly. When using #if 0, it uses a version of alpha that appears as if it should do exactly the same, however, it causes a segfault while doing " void operator=(const U& in) { *this = in; }", and I think it's in an infinite loop there, maybe operator= is calling itself all the time. My questions are: Why does the one version work, while the other segfaults? Are there better ways than the "opaque()" function, to fix the crash?
Advertisement
1° It's an infinite loop.

void operator=(const U& in) { // for alpha LHS and const U& RHS  *this = in; // LHS is alpha, RHS is const U&, guess what is called?} 


2° Specify that you want the base version of operator=:

void operator=(const U& in) {   this->U::operator=(in); } 

Quote:Original post by ToohrVyk
this->U::operator=(in);


Super! I wanted to do something like that, but I didn't know the syntax :)
Completely off-topic, but:

RGB(T R, T G, T B){    this->R = R;    this->G = G;    this->B = B;}


Can be replaced with:

RGB (T R, T G, T B) : R (R), G (G), B (B){}


Or if there is ever a chance T will be a complex type:

RGB (const T &R, const T &G, const T &B) : R (R), G (G), B (B){}


Anyway, it looked like you didn't realise you can have variables with the same name as the class's members in a constructor. Also, by using an initializer list (i.e. R (R), etc) you save yourself an object copy, as it is constructed with the correct value, as opposed to it being constructed with the default constructor then an assignment being performed. This has no affect on built-in types, but again you can get big performance gains from complex objects.

This topic is closed to new replies.

Advertisement