2011-01-26 1 views
10

J'ai travaillé sur mon programme et j'ai décidé d'activer certaines optimisations en utilisant g++ -O3. Soudain, mon programme a commencé à segmenter. J'ai chassé le code problématique, et réduit mon programme à quelque chose qui se sépare toujours (seulement en utilisant des optimisations de niveau 3). J'espérais que quelqu'un pourrait jeter un coup d'oeil rapide au code (j'ai essayé de minimiser autant que possible):Activer l'optimisation g ++ provoque segfault - Je ne comprends pas

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

J'aimerais un aperçu des raisons pour lesquelles ce code segfaults que lors de l'utilisation des optimisations et comment l'arrêter de le faire. Merci!

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

Edit: Sur demande, les constructeurs pour alg :: vecteur

 
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: Ajout sortie gdb lors de la compilation avec -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 pour rt :: Couleur .

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

Avez-vous essayé de compiler avec -g et pour voir si le tout est backtrace utilisable? –

+0

Je suis curieux de savoir pourquoi vous ne compilez pas avec 'g ++ src/*. Cpp -Iinclude -O3'. Avec l'approche 'xargs', le compilateur construit chaque fichier dans' a.out', donc je suppose qu'ils ont tous 'main()'. – chrisaycock

+1

pouvez-vous poster le constructeur de copie de 'alg :: vector'? – Naveen

Répondre

6

Lors du calcul intensity * color, indirectement cet opérateur est appelé:

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

Il prétend renvoyer une référence à un Color, mais ne fonctionne pas. Il doit renvoyer une référence à *this, comme les autres opérateurs font:

return *this; 
+0

+1. Comment est-ce pas une erreur de compilateur? L'absence de valeur de retour est-elle un avertissement dans gcc? – James

+1

@James: C'est un avertissement qui est activé si vous spécifiez '-Wall'. – sth

+2

Ah. Je suppose qu'il y a une leçon à apprendre ici ... toujours utiliser -Wall. – James

2

Vous devez réaliser que ce n'est pas l'optimisation qui brise votre code, le code est déjà cassé. Je ne peux pas vraiment voir ce qui se passe juste en regardant ces morceaux mais en regardant comme si vous étiez en train de créer une nouvelle déclaration, j'essaierais de diriger mes efforts vers la vérification des paramètres d'entrée de vos nouvelles fonctions. Parmi les nombreuses choses qui se produisent au cours d'une optimisation 03, le compilateur va essayer d'aligner les appels de fonctions, dérouler vos boucles, créer de nouvelles variables et se débarrasser de celles-ci afin d'accélérer votre exécution. Dans un premier temps, vérifiez si vous avez des boucles et assurez-vous que si vous faites quelque chose comme < strlen (str) que l'instruction n'est pas folle et affirmez que les paramètres d'entrée qui ne devraient pas être NULL ne sont pas NULL.

Espérons que cela aide.

1

Je ne suis pas sûr que ce soit le problème que vous voyez, mais si vous avez une classe avec des fonctions virtuelles qui est utilisé polymorphically, il devrait avoir un destructor virtuel:

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

Actuellement, si vous delete la variable light dans votre principale, le ~Light destructeur serait appelé (puisque la variable a le type Light*), au lieu de la correcte ~Point un. Rendre le destructeur virtuel corrige ceci.

+0

J'ai ajouté le destructeur virtuel, en vain ... La segfault se produit avant que l'objet ne soit à nouveau détruit, il arrive sur la ligne avec 'new rt :: light :: Point'.Tout ce qui n'est même plus passé est exécuté. – robrene

+0

@robrene: Je m'en doutais, puisque l'objet * n'est * jamais * réellement détruit dans l'exemple de code ... Mais ça devrait quand même être un pas dans la bonne direction. – sth

2

Il est temps d'apprendre à déboguer avec gdb!

tout recompiler le code source avec -g:

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

Lancez ensuite gdb, chargez votre fichier et l'exécuter:

gdb 
file a.out 
run 

gdb vous amènera à une invite de commande lorsque votre programme frappe le segfault. À l'invite (gdb) tapez "bt" et appuyez sur Entrée. Cela vous donnera la trace de la pile. La première image de la pile sera la ligne de code à l'origine de l'erreur de segmentation. À partir de là, si c'est évident, corrigez-le sinon, ajoutez la sortie à votre question. Parfois, gdb n'est pas très bon pour déboguer du code dans les constructeurs, mais essayez-le d'abord et voyez ce qu'il dit.

+0

J'ai ajouté la sortie gdb à la publication originale. Merci de m'avoir donné le guide rapide sur le débogage! Je ne suis pas sûr de savoir comment cette sortie m'aide, puisque je savais déjà où la segfault se passait. Je ne sais pas pourquoi ... – robrene

0

Il peut y avoir une certaine confusion à l'aide de la variable membre pos et de la variable variable pos, essayez de leur donner des noms de variables différents.

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

+1

Il ne devrait pas y avoir de confusion. L'argument masque la variable membre. Il est assez courant d'avoir des choses comme 'pos (pos)' dans une liste d'initialisation. –