Sign in to follow this  

Segfault that I can't explain

This topic is 4090 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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

This topic is 4090 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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