I've been working on my program, and I decided to turn on some optimizations using g++ -O3
. Suddenly, my program started segfaulting. I've hunted the problematic code down, and minimized my program to something that still segfaults (only when using level 3 optimizations). I was hoping someone could take a quick peek at the code (I tried minimizing it as much as possible):
// src/main.cpp
#include "rt/lights/point.hpp"
int main(int argc, char **argv)
{
rt::Light *light = new rt::light::Point(alg::vector(.0f, 5.0f, 5.0f), rt::Color(1.0f), .5f);
return 0;
}
// include/rt/lights/point.hpp
#ifndef RT_LIGHT_POINT_HPP_
#define RT_LIGHT_POINT_HPP_
#include "rt/accelerator.hpp"
#include "rt/color.hpp"
#include "rt/intersection.hpp"
#include "rt/light.hpp" // abstract
namespace rt {
namespace light {
class Point : public Light
{
public:
Point(alg::vector pos, Color color, float intensity) : Light(intensity * color), pos(pos) {}
Color get_contrib(const Intersection&, const Accelerator&, const alg::vector& toViewer) const;
private:
alg::vector pos;
};
} // namespace light
} // namespace rt
#endif
// include/rt/light.hpp
#ifndef RT_LIGHT_HPP_
#define RT_LIGHT_HPP_
#include "algebra/vector.hpp"
#include "rt/color.hpp"
namespace rt {
class Intersection;
class Accelerator;
class Light
{
public:
Light(Color intensity) : intensity(intensity) {}
virtual Color get_contrib(const Intersection&, const Accelerator&, const alg::vector& toViewer) const = 0;
Color get_intensity() const {return intensity;}
protected:
Color intensity;
};
} // namespace rt
#endif
I would love some insight on why this code only segfaults when using optimizations, and how to stop it from doing so. Thanks!
$ find src/ -name "*.cpp" | xargs g++ -I include/ -O3
$ ./a.out
Segmentation fault
Edit: By request, the constructors for alg::vector
struct vector { float x, y, z; vector() : x(.0f), y(.0f), z(.0f) {} explicit vector(float f) : x(f), y(f), z(f) {} vector(float x, float y, float z) : x(x), y(y), z(z) {} // ...
Edit2: Adding gdb output when compiling with -g
(gdb) file a.out Reading symbols from /home/rob/devel/gbug/a.out...done. (gdb) run Starting program: /home/rob/devel/gbug/a.out Program received signal SIGSEGV, Segmentation fault. rt::light::Point::Point (this=0x804b008, pos=..., color=..., intensity=0.5) at src/rt/lights/point.cpp:13 13 Point::Point(alg::vector pos, Color color, float intensity) : Light(intensity * color), pos(pos) (gdb) bt #0 rt::light::Point::Point (this=0x804b008, pos=..., color=..., intensity=0.5) at src/rt/lights/point.cpp:13 #1 0x08048898 in main (argc=1, argv=0xbffff3e4) at src/main.cpp:5
Edit3: Sources for rt::Color.
// include/rt/color.hpp #ifndef RT_COLOR_HPP_ #define RT_COLOR_HPP_ #include "algebra/vector.hpp" namespace rt { /******************************************************************************* * CLASS DEFINITION */ struct Color { float r, g, b; Color() : r(.0f), g(.0f), b(.0f) {} explicit Color(float f) : r(f), g(f), b(f) {} Color(float r, float g, float b) : r(r), g(g), b(b) {} Color& operator+= (const Color&); Color& operator*= (const Color&); Color& operator*= (float); }; /******************************************************************************* * MEMBER OPERATORS */ inline Color& Color::operator+= (const Color& other) { r += other.r; g += other.g; b += other.b; return *this; } inline Color& Color::operator*= (const Color& other) { r *= other.r; g *= other.g; b *= other.b; return *this; } inline Color& Color::operator*= (float f) { r *= f; g *= f; b *= f; } /******************************************************************************* * ADDITIONAL OPERATORS */ inline Color operator+ (Color lhs, const Color& rhs) { return lhs += rhs; } inline Color operator* (Color lhs, const Color& rhs) { return lhs *= rhs; } inline Color operator* (Color c, float f) { return c *= f; } inline Color operator* (float f, Color c) { return c *= f; } } // namespace rt #endif
Best Answer
When calculating
intensity * color
, indirectly this operator is called:It claims to return a reference to a
Color
, but doesn't. It should return a reference to*this
, like the other operators do: