2011-01-26 15 views
10

He estado trabajando en mi programa, y ​​decidí activar algunas optimizaciones usando g++ -O3. De repente, mi programa comenzó segfaulting. He cazado el código problemático y minimicé mi programa a algo que aún falla (solo cuando utilizo optimizaciones de nivel 3). Tenía la esperanza de que alguien pudiera echar un vistazo rápido en el código (He intentado minimizar tanto como sea posible):Encender la optimización de g ++ causa segfault - No lo entiendo

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

me encantaría una idea de por qué este código sólo segfaults al utilizar optimizaciones, y cómo detenerlo de hacerlo. ¡Gracias!

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

Editar: A petición, los constructores para 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: La adición de resultados GDB al compilar con -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: Fuentes para 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 
+1

¿Ha intentado compilar con -g así para ver si la traza inversa es en absoluto utilizable? –

+0

Tengo curiosidad de por qué no compila con 'g ++ src/*. Cpp -Iinclude -O3'. Con el enfoque 'xargs', el compilador construiría cada archivo en' a.out', así que supongo que todos tienen 'main()'. – chrisaycock

+1

puede publicar el constructor de copia de 'alg :: vector'? – Naveen

Respuesta

6

Al calcular intensity * color, indirectamente, este operador se llama:

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

Pretende devolver una referencia a un Color, pero no lo hace. Se debe devolver una referencia a *this, al igual que los otros operadores hacen:

return *this; 
+0

+1. ¿Cómo es que esto no es un error del compilador? ¿La falta de valor de retorno es una advertencia en gcc? – James

+1

@Juegos: es una advertencia que se habilita si especifica '-Wall'. – sth

+2

Ah. Supongo que hay una lección que aprender aquí ... siempre use -Wall. – James

2

Debe darse cuenta de que no es la optimización lo que está rompiendo su código, el código ya está roto. No puedo ver exactamente qué está sucediendo con tan solo mirar esos fragmentos, pero viendo que está fallando en una declaración nueva, trataría de dirigir mis esfuerzos hacia la verificación de los parámetros de entrada de sus nuevas funciones. Entre las muchas cosas que suceden durante una optimización de 03 se encuentra que el compilador intentará realizar llamadas de función en línea, desenrollar sus bucles y crear nuevas variables, así como deshacerse de las mismas para acelerar su ejecución. Como primer paso, revise en cualquier lugar donde tenga bucles y asegúrese de que si está haciendo algo como i < strlen (str) que la declaración no está loca y afirme que los parámetros de entrada que no deberían ser NULL en realidad no son NULL.

Espero que esto ayude.

1

no estoy seguro de si este es el tema que está viendo, pero si usted tiene una clase con funciones virtuales que se utiliza polimórfica, debería haber un destructor virtual:

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

Actualmente, si sería delete la variable light en su principal, se llamaría al destructor ~Light (ya que la variable tiene el tipo Light*), en lugar del ~Point correcto. Hacer que el destructor virtual solucione esto.

+0

Agregué el destructor virtual, en vano ... El segfault ocurre antes de que el objeto se destruya nuevamente, sucede en la línea con 'new rt :: light :: Point'.Cualquier cosa pasada que ni siquiera se ejecuta más. – robrene

+0

@robrene: Lo sospechaba mucho, ya que el objeto * * no se destruye realmente en el código de muestra ... Pero de todos modos debería ser un paso en la dirección correcta. – sth

2

¡Hora de aprender a depurar con gdb!

recompilación todo el código fuente con -g:

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

A continuación, ejecute el BGF, cargue el archivo y ejecutarlo:

gdb 
file a.out 
run 

BGF le llevará a un símbolo del sistema cuando el programa golpea el segfault. En el indicador (gdb), escriba "bt" y presione enter. Le dará el rastro de la pila. El primer cuadro de la pila será la línea de código que causó la falla de segmentación.

A partir de ahí si es obvio corregirlo de lo contrario, agregue el resultado a su pregunta. A veces, gdb no es muy bueno en el código de depuración que está en los constructores, pero pruébalo primero y mira lo que dice.

+0

Agregué el resultado de gdb a la publicación original. Gracias por darme la guía rápida sobre la depuración! No estoy muy seguro de cómo me ayuda esta salida, ya que sabía dónde estaba ocurriendo el segfault. Simplemente no sé por qué ... – robrene

0

Puede haber cierta confusión al usar la variable miembro pos y la variable pasada pos, intente nombrarlas con diferentes nombres de variable.

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

+1

No debería haber ninguna confusión. El argumento oculta la variable miembro. Es bastante común tener cosas como 'pos (pos)' en una lista de inicialización. –

Cuestiones relacionadas