2011-01-26 28 views
10

Tôi đã làm việc trên chương trình của mình và tôi đã quyết định bật một số tối ưu hóa bằng cách sử dụng g++ -O3. Đột nhiên, chương trình của tôi bắt đầu segfaulting. Tôi đã tìm kiếm mã có vấn đề và giảm thiểu chương trình của tôi thành một chương trình nào đó vẫn còn bị phân đoạn (chỉ khi sử dụng tối ưu hóa mức 3). Tôi đã hy vọng ai đó có thể mất một peek nhanh chóng vào mã (Tôi đã cố gắng giảm thiểu nó càng nhiều càng tốt):Bật tối ưu hóa g ++ gây ra segfault - Tôi không nhận được nó

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

Tôi rất thích một số cái nhìn sâu sắc về lý do tại sao mã này chỉ segfaults khi sử dụng tối ưu hóa, và làm thế nào để ngăn chặn nó làm như vậy. Cảm ơn!

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

Edit: Theo yêu cầu, các nhà thầu cho 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: Thêm đầu ra gdb khi biên dịch với -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: Nguồn cho rt :: Màu .

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

Bạn đã thử biên dịch bằng -g để xem liệu có thể sử dụng backtrace không? –

+0

Tôi tò mò tại sao bạn không biên dịch với 'g ++ src/*. Cpp -Iinclude -O3'. Với cách tiếp cận 'xargs', trình biên dịch sẽ xây dựng mỗi tệp thành' a.out', vì vậy tôi giả sử tất cả chúng đều có 'main()'. – chrisaycock

+1

bạn có thể đăng các nhà xây dựng bản sao của 'alg :: vector'? – Naveen

Trả lời

6

Khi tính toán intensity * color, gián tiếp điều hành này được gọi là:

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

Nó tuyên bố để trả về một tham chiếu đến một Color, nhưng không. Nó phải trả về một tham chiếu đến *this, giống như các toán tử khác làm:

return *this; 
+0

+1. Làm thế nào là điều này không phải là một lỗi biên dịch? Việc thiếu giá trị trả về có phải là cảnh báo trong gcc không? – James

+1

@James: Đó là cảnh báo được bật nếu bạn chỉ định '-Wall'. – sth

+2

Ah. Tôi đoán có một bài học để được học ở đây ... luôn luôn sử dụng -Wall. – James

2

Bạn phải nhận ra rằng đó không phải là tối ưu hóa vi phạm mã của bạn, mã đã bị hỏng. Tôi không thể nhìn thấy những gì đang xảy ra chỉ bằng cách nhìn vào những khối đó nhưng nhìn thấy như thể bạn đang segfaulting trên một tuyên bố mới, tôi sẽ cố gắng và chỉ đạo những nỗ lực của tôi đối với việc kiểm tra các thông số đầu vào của các chức năng mới của bạn. Trong số rất nhiều điều xảy ra trong tối ưu hóa 03 là trình biên dịch sẽ cố gắng thực hiện các cuộc gọi hàm nội tuyến, bỏ vòng lặp của bạn và tạo các biến mới cũng như loại bỏ các biến đó để đẩy nhanh quá trình thực hiện của bạn. Bước đầu tiên, kiểm tra lại ở bất cứ nơi nào bạn có vòng lặp và đảm bảo rằng bạn đang làm một cái gì đó như i < strlen (str) rằng câu lệnh không điên và khẳng định rằng tham số đầu vào không được NULL là thực tế không phải NULL.

Hy vọng điều này sẽ hữu ích.

1

Tôi không chắc chắn nếu điều này là vấn đề bạn đang nhìn thấy, nhưng nếu bạn có một lớp học với chức năng ảo được sử dụng polymorphically, cần có một destructor ảo:

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

Hiện tại, nếu bạn delete biến số light trong chính của bạn, hàm hủy ~Light sẽ được gọi (vì biến có loại Light*), thay vì số ~Point chính xác. Làm cho các destructor ảo sửa lỗi này.

+0

Tôi đã thêm destructor ảo, vô ích ... Segfault xảy ra trước khi đối tượng bị phá hủy một lần nữa, nó xảy ra trên dòng với 'new rt :: light :: Point'.Bất cứ điều gì quá khứ mà thậm chí không bị xử tử nữa. – robrene

+0

@robrene: Tôi nghi ngờ nhiều, vì đối tượng * là * không bao giờ thực sự bị phá hủy trong mã mẫu ... Nhưng nó phải là một bước đi đúng hướng. – sth

2

Thời gian để tìm hiểu cách gỡ lỗi bằng gdb!

biên dịch lại tất cả các mã nguồn với -g:

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

Sau đó chạy gdb, tải tập tin của bạn, và thực hiện nó:

gdb 
file a.out 
run 

gdb sẽ đưa bạn đến một cửa sổ lệnh khi chương trình của bạn truy cập segfault. Tại dấu nhắc (gdb) gõ "bt" và nhấn enter. Nó sẽ cho bạn dấu vết ngăn xếp. Khung đầu tiên của ngăn xếp sẽ là dòng mã gây ra lỗi phân đoạn.

Từ đó nếu nó rõ ràng là sửa chữa nó, nếu không hãy thêm đầu ra cho câu hỏi của bạn. Đôi khi gdb không phải là tuyệt vời tại gỡ lỗi mã đó là trong nhà xây dựng nhưng hãy thử nó đầu tiên và xem những gì nó nói.

+0

Tôi đã thêm đầu ra gdb vào bài đăng gốc. Cảm ơn đã cho tôi hướng dẫn nhanh về gỡ lỗi! Tôi không hoàn toàn chắc chắn như thế nào đầu ra này giúp tôi, kể từ khi tôi đã biết nơi segfault đã xảy ra. Tôi chỉ không biết tại sao ... – robrene

0

Có thể có một số nhầm lẫn bằng cách sử dụng biến thành viên pos và được truyền trong biến số pos, hãy thử đặt tên cho các tên biến khác nhau.

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

+1

Không nên có bất kỳ sự nhầm lẫn nào. Đối số ẩn biến thành viên. Nó khá phổ biến để có những thứ như 'pos (pos)' trong một danh sách khởi tạo. –

Các vấn đề liên quan