打开 g++优化导致段错误 - 我不明白
我一直在研究我的程序,并决定使用 g++ -O3
打开一些优化。突然,我的程序开始出现段错误。我已经找到了有问题的代码,并将我的程序最小化为仍然存在段错误的代码(仅当使用 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) {} // ...
Edit2:使用 -g
编译时添加 gdb 输出
(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
I've been working on my program, and I decided to turn on some optimizations using g++ -O3
. Suddenly, my program started segfaulting. I've hunted the problematic code down, and minimized my program to something that still segfaults (only when using level 3 optimizations). I was hoping someone could take a quick peek at the code (I tried minimizing it as much as possible):
// 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
I would love some insight on why this code only segfaults when using optimizations, and how to stop it from doing so. Thanks!
$ find src/ -name "*.cpp" | xargs g++ -I include/ -O3
$ ./a.out
Segmentation fault
Edit: By request, the constructors for 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: Adding gdb output when compiling with -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 for 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
当计算
intensity * color
时,会间接调用此运算符:它声称返回对
Color
的引用,但事实并非如此。它应该返回对*this
的引用,就像其他运算符一样:When calculating
intensity * color
, indirectly this operator is called:It claims to return a reference to a
Color
, but doesn't. It should return a reference to*this
, like the other operators do:是时候学习如何使用 gdb 进行调试了!
使用 -g 重新编译所有源代码:
然后运行 gdb,加载文件并执行它:
当程序遇到段错误时,gdb 会将您带到命令提示符。在 (gdb) 提示符下键入“bt”并按 Enter 键。它会给你堆栈跟踪。堆栈的第一帧将是导致分段错误的代码行。
如果很明显,请从那里修复它,否则将输出添加到您的问题中。有时 gdb 不擅长调试构造函数中的代码,但请先尝试一下,看看它说了什么。
Time to learn how to debug with gdb!
Recompile all the source code with -g:
Then run gdb, load your file, and execute it:
gdb will bring you to a command prompt when your program hits the segfault. At the (gdb) prompt type "bt" and hit enter. It will give you the stack trace. The first frame of the stack will be the line of code that caused the segmentation fault.
From there if it's obvious fix it otherwise add the output to your question. Sometimes gdb isn't great at debugging code that's in constructors but try it first and see what it says.
您必须意识到,并不是优化破坏了您的代码,而是代码已经被破坏了。仅通过查看这些块我无法完全了解发生了什么,但看到好像您在新语句上出现了段错误,我会尝试将我的精力集中在检查新函数的输入参数上。在 03 优化期间发生的许多事情之一是,编译器将尝试内联函数调用、展开循环、创建新变量以及删除变量以加速执行。第一步,仔细检查任何有循环的地方,并确保你正在做类似 i < > 的事情。 strlen(str) 认为该语句并不疯狂,并断言不应该为 NULL 的输入参数实际上也不是 NULL。
希望这有帮助。
You must realize that it's not the optimization that's breaking your code, the code is already broken. I can't quite see what is going on just by looking at those chunks but seeing as though you are segfaulting on a new statement, I would try and direct my efforts toward checking the input parameters of your new functions. Amongst the many things that happens during an 03 optimization is that the compiler will try to inline function calls, unroll your loops, and create new variables as well as get rid of ones in order to accelerate your execution. As a first step, double check anywhere you have loops and make sure if you're doing something like i < strlen(str) that the statement is not crazy and assert that the input parameters that should not be NULL are in fact not NULL.
Hope this helps.
我不确定这是否是您遇到的问题,但如果您有一个具有多态使用的虚拟函数的类,它应该有一个虚拟析构函数:
目前,如果您要
删除
<在 main 中的 code>light 变量中,将调用~Light
析构函数(因为该变量的类型为Light*
),而不是正确的~点
一。使析构函数成为虚拟可以解决这个问题。I'm not sure if this is the issue you are seeing, but if you have a class with virtual functions that is used polymorphically, it should have a virtual destructor:
Currently, if you would
delete
thelight
variable in your main, the~Light
destructor would be called (since the variable has typeLight*
), instead of the correct~Point
one. Making the destructor virtual fixes this.使用成员变量 pos 和传入的变量 pos 可能会出现一些混淆,请尝试将它们命名为不同的变量名称。
Point(alg::vector pos, Color 颜色, 浮动强度) : Light(强度 * 颜色), pos(pos) {}
There might be some confusion using the member variable pos and the passed in variable pos, try naming them different variable names.
Point(alg::vector pos, Color color, float intensity) : Light(intensity * color), pos(pos) {}