Включение оптимизации g ++ вызывает segfault - я не понимаю - PullRequest
10 голосов
/ 26 января 2011

Я работал над своей программой и решил включить некоторые оптимизации, используя g++ -O3.Внезапно моя программа начала segfaulting.Я выследил проблемный код и свел свою программу к чему-то, что все еще вызывает ошибки (только при использовании оптимизации уровня 3).Я надеялся, что кто-то может быстро взглянуть на код (я пытался свести его к минимуму):

// 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

Я хотел бы получить представление о том, почему этот код вызывает ошибки только при использовании оптимизаций, и какостановить это от этого.Спасибо!

$ find src/ -name "*.cpp" | xargs g++ -I include/ -O3
$ ./a.out
Segmentation fault

Редактировать: По запросу конструкторы для 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) {}
    // ...

Редактировать2: Добавление вывода GDB при компиляции с -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: источники для 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

Ответы [ 5 ]

6 голосов
/ 26 января 2011

При вычислении intensity * color косвенно вызывается этот оператор:

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

Он утверждает, что возвращает ссылку на Color, но не возвращает.Он должен возвращать ссылку на *this, как это делают другие операторы:

return *this;
2 голосов
/ 26 января 2011

Пора научиться отлаживать с помощью gdb!

Перекомпилировать весь исходный код с помощью -g:

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

Затем запустите gdb, загрузите файл и выполните его:

gdb
file a.out
run

GDB приведет вас к командной строке, когда ваша программа попадет в segfault.В приглашении (gdb) введите «bt» и нажмите ввод.Это даст вам трассировку стека.Первый кадр стека будет строкой кода, которая вызвала ошибку сегментации.

Оттуда, если это очевидно, исправьте это, иначе добавьте вывод к вашему вопросу.Иногда GDB не очень хорош в отладке кода, который находится в конструкторах, но сначала попробуйте его и посмотрите, что он говорит.

2 голосов
/ 26 января 2011

Вы должны понимать, что не оптимизация нарушает ваш код, код уже сломан. Я не могу понять, что происходит, просто посмотрев на эти куски, но, видя, что вы запутались в новом утверждении, я бы попытался направить свои усилия на проверку входных параметров ваших новых функций. Среди многих вещей, которые происходят во время оптимизации 03, это то, что компилятор будет пытаться встроить вызовы функций, развернуть ваши циклы и создать новые переменные, а также избавиться от них, чтобы ускорить ваше выполнение. В качестве первого шага, дважды проверьте, где у вас есть циклы, и убедитесь, что вы делаете что-то вроде i

Надеюсь, это поможет.

1 голос
/ 26 января 2011

Я не уверен, что это проблема, которую вы видите, но если у вас есть класс с виртуальными функциями, который используется полиморфно, он должен иметь виртуальный деструктор:

class Light {
   ...
   virtual ~Light {}
   ...
};

В настоящее время, если* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * [Поэтому потому, что переменная имеет тип Light*), будет вызываться delete переменная light в вашей основной сети.Создание виртуального деструктора исправляет это.

0 голосов
/ 26 января 2011

Может возникнуть некоторая путаница с использованием переменной-члена pos и переданной в переменную pos, попробуйте назвать их разными именами переменных.

Point(alg::vector pos, Color color, float intensity) : Light(intensity * color), pos(pos) {}

...