2011-01-26 12 views
10

Ho lavorato sul mio programma, e ho deciso di accendere alcune ottimizzazioni che utilizzano g++ -O3. All'improvviso, il mio programma ha iniziato la segfault. Ho cacciato il codice problematico e ridotto il mio programma a qualcosa che ancora segfaults (solo quando si utilizzano le ottimizzazioni di livello 3). Speravo che qualcuno potrebbe prendere una rapida occhiata al codice (ho provato a minimizzare il più possibile):Accensione g ++ ottimizzazione provoca segfault - Io non capisco

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

mi piacerebbe qualche intuizione sul motivo per cui questo codice segfaults solo quando si utilizza ottimizzazioni, e come fermarla dal farlo. Grazie!

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

Edit: A richiesta, i costruttori per 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: Aggiunta di uscita gdb quando si compila 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: Fonti per rt :: Colore .

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

Hai provato la compilazione con -g pure per vedere se il backtrace è affatto utilizzabile? –

+0

Sono curioso di sapere perché non si compila con 'g ++ src/*. Cpp -Iinclude -O3'. Con l'approccio 'xargs', il compilatore costruisce ogni file in' a.out', quindi presumo che abbiano tutti 'main()'. – chrisaycock

+1

puoi pubblicare il costruttore di copia di 'alg :: vector'? – Naveen

risposta

6

Nel calcolo intensity * color, indirettamente questo operatore è chiamato:

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

Essa sostiene di restituire un riferimento a un Color, ma non lo fa. Dovrebbe restituire un riferimento alla *this, come gli altri operatori fanno:

return *this; 
+0

+1. In che modo non si tratta di un errore del compilatore? La mancanza di valore di ritorno è un avvertimento in gcc? – James

+1

@James: è un avviso che viene abilitato se si specifica '-Wall'. – sth

+2

Ah. Immagino ci sia una lezione da imparare qui ... usa sempre -Wall. – James

2

È necessario rendersi conto che non è l'ottimizzazione che sta infrangendo il codice, il codice è già rotto. Non riesco a vedere cosa sta succedendo solo guardando quei pezzi, ma vedendo come se stessimo segfault su una nuova affermazione, proverei a dirigere i miei sforzi verso il controllo dei parametri di input delle nuove funzioni. Tra le molte cose che accadono durante un ottimizzazione 03 è che il compilatore proverà a chiamate di funzioni in linea, srotolare i loop, e creare nuove variabili e sbarazzarsi di quelle al fine di accelerare l'esecuzione. Come primo passo, doppio controllo ovunque ci sia loop e assicurarsi che se stai facendo qualcosa di simile i < strlen (str) che la dichiarazione non è pazzo e affermare che i parametri di input che non dovrebbero essere NULL sono in realtà non NULL.

Spero che questo aiuti.

1

non sono sicuro se questo è il problema che si sta vedendo, ma se si dispone di una classe con funzioni virtuali che viene utilizzato polimorfico, dovrebbe avere un distruttore virtuale:

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

Attualmente, se si avrebbe delete la variabile light nel vostro principale, il distruttore ~Light sarebbe stato chiamato (in quanto la variabile è di tipo Light*), al posto del corretto ~Point uno. Rendere questo il distruttore virtuale lo corregge.

+0

Ho aggiunto il distruttore virtuale, senza alcun risultato ... Il segfault avviene prima che l'oggetto venga nuovamente distrutto, avviene sulla riga con 'new rt :: light :: Point'.Qualunque cosa sia passata non viene più eseguita. – robrene

+0

@robrene: Lo sospettavo, dal momento che l'oggetto * non * è mai stato effettivamente distrutto nel codice di esempio ... Ma dovrebbe comunque essere un passo nella giusta direzione. – sth

2

tempo per imparare come eseguire il debug con gdb!

Riconversione tutto il codice sorgente con -g:

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

Poi gestita gdb, caricare il file, ed eseguirlo:

gdb 
file a.out 
run 

gdb vi porterà ad un prompt dei comandi quando il programma colpisce il segfault. Al prompt (gdb) digita "bt" e premi invio. Ti darà la traccia dello stack. Il primo frame dello stack sarà la linea di codice che ha causato l'errore di segmentazione.

Da lì, se è evidente difficoltà altrimenti aggiungere l'uscita alla tua domanda. A volte gdb non è ottimo per il debug del codice presente nei costruttori, ma prima provalo e guarda cosa dice.

+0

Ho aggiunto l'output gdb al post originale. Grazie per avermi dato la guida rapida per il debugging! Non sono abbastanza sicuro di come questa uscita mi aiuti, poiché sapevo già dove stava accadendo il segfault. Solo non so perché ... – robrene

0

Ci potrebbe essere un po 'di confusione usando la variabile membro pos e la variabile passata in pos, provare a nominarli con nomi di variabili differenti.

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

+1

Non ci dovrebbe essere alcuna confusione. L'argomento nasconde la variabile membro. È piuttosto comune avere cose come 'pos (pos)' in una lista di inizializzazione. –