Sign in to follow this  
Lode

Segfault that I can't explain

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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);
}

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
this->U::operator=(in);


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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this