Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turning on g++ optimization causes segfault - I don't get it

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
like image 391
robrene Avatar asked Jan 26 '11 15:01

robrene


People also ask

How is Segfault caused?

In practice, segfaults are almost always due to trying to read or write a non-existent array element, not properly defining a pointer before using it, or (in C programs) accidentally using a variable's value as an address (see the scanf example below).

How do you solve a segmentation fault in C++?

It can be resolved by having a base condition to return from the recursive function. A pointer must point to valid memory before accessing it.

What causes segmentation fault core dumped C?

The third link provides an example of Segmentation Fault (Core dumped) . The problem there is caused mainly due to trying to access a part of string which is out of bound. Segmentation Fault (core dumped) C++ This is also an example.


2 Answers

When calculating intensity * color, indirectly this operator is called:

inline Color& Color::operator*= (float f)
{
    r *= f;
    g *= f;
    b *= f;
}

It claims to return a reference to a Color, but doesn't. It should return a reference to *this, like the other operators do:

return *this;
like image 109
sth Avatar answered Sep 21 '22 08:09

sth


Time to learn how to debug with gdb!

Recompile all the source code with -g:

find src/ -name "*.cpp" | xargs g++ -I include/ -O3 -g

Then run gdb, load your file, and execute it:

gdb
file a.out
run

gdb will bring you to a command prompt when your program hits the segfault. At the (gdb) prompt type "bt" and hit enter. It will give you the stack trace. The first frame of the stack will be the line of code that caused the segmentation fault.

From there if it's obvious fix it otherwise add the output to your question. Sometimes gdb isn't great at debugging code that's in constructors but try it first and see what it says.

like image 32
gravitron Avatar answered Sep 19 '22 08:09

gravitron