【问题标题】:Vectors, "virtual", Segmentation Fault on function call向量,“虚拟”,函数调用上的分段错误
【发布时间】:2009-12-07 09:52:41
【问题描述】:

我在尝试调用属于“形状”指针向量一部分的对象内的函数时遇到分段错误

我的问题出在这个函数上::

    Point findIntersection(Point p, Point vecDir, int *status)
    {

        Point noPt;
        for (int i = 0; i < shapes.size(); i++)
        {
            Point temp;
            cout << "Shapes size" << shapes.size() << endl;
**SEGMENTATIONFAULT HERE >>>>>**            bool intersect = shapes[0]->checkIntersect(p, vecDir, &temp);
            if (intersect)
            {
                *status = 1;    // Code 1 for intersecting the actual shape
                return temp;
            }

        }

        return noPt;
    }

最初,我只添加一个形状:

void createScene()
{

    image = QImage(width, height, 32); // 32 Bit

    Sphere s(Point(0.0,0.0,-50.0), 40.0);
    shapes.push_back(&s);
    cout << shapes.size() <<endl;
}

所以我有一个全局的“形状”向量。 矢量形状;

我有一个班级形状

#include "Point.h"
#ifndef SHAPE_H
#define SHAPE_H
using namespace std;
class Shape
{
    public: 
    Shape() {}
    ~Shape(){}
    virtual bool checkIntersect(Point p, Point d, Point *temp) {};  // If intersects, return true else false.
    virtual void printstuff() {};

};
#endif

还有一个 Sphere 类

#include "shape.h"
#include <math.h>
#include <algorithm>
using std::cout;
using std:: endl;
using std::min;

class Sphere : public Shape
{
    public:
    Point centerPt;
    double radius;

    Sphere(Point center, double rad)
    {
        centerPt = center;
        radius = rad;
    }

    bool checkIntersect(Point p, Point vecDir, Point *temp)
    {
        cout << "Hi" << endl;
    /*
        Point _D = p - centerPt;
        double a = Point :: dot(vecDir, vecDir);
        double b = 2 * ( Point :: dot(vecDir, _D) );
        double c = (Point :: dot(_D,_D)) - (radius * radius);

        // Quadratic Equation
        double tempNum = b * b - 4 * a * c;
        if (tempNum < 0)
        {
            return false;
        } else
        {
            double t1 = ( -b + sqrt(tempNum) ) / (2 * a);
            double t2 = ( -b - sqrt(tempNum) ) / (2 * a);
            double t;

            if (t1 < 0 && t2 > 0) { t = t2; }
            else if (t2 < 0 && t1 > 0) { t = t1; }
            else if ( t1 < 0 && t2 < 0 ) { return false; }
            else
            {
                t = min(t1, t2);
            }

            Point p1 = p + (vecDir * t);

            if (p1.z > 0)           // Above our camera
            {
                return false;
            } else 
            {
                temp = &p1;
                return true;
            }

        }
    */
        return false;
    }
};

【问题讨论】:

  • 显而易见的问题是如何填充“形状”向量?
  • 我认为这不是问题,但 Shape 中的析构函数应该是虚拟的,checkIntersectprintStuff 可能应该是纯虚拟的(删除 {} 并替换为 @987654328 @)
  • 我尝试将其更改为 =0 仍然出现分段错误:(
  • 还可以在向形状中添​​加元素的位置添加代码。

标签: c++


【解决方案1】:

问题出在这里:

Sphere s(Point(0.0,0.0,-50.0), 40.0);
shapes.push_back(&s);

此时,您已经在堆栈上本地创建了 Sphere s,并且您已将其地址推送到您的向量中。当您离开作用域时,本地对象被释放,因此您存储在向量中的地址现在指向您不再拥有的内存并且其内容未定义。

相反,做

Sphere *s = new Sphere(Point(0.0,0.0,-50.0), 40.0);
shapes.push_back(s);

从堆中分配球体,使其持久存在。完成后请务必delete

【讨论】:

  • 或者更好的是,使用 shared_ptr
  • @Billy:他仍然必须使用 new 分配他传递给 shared_ptr 的内存,他不能只传递堆栈上的地址;所以使用 shared_ptr 并没有消除理解他的原始代码发生了什么的需要。
【解决方案2】:

您在矢量形状中放置了一个局部变量的地址。从您的函数 createScene() 退出后,此地址将变为无效。

void createScene()
{

    image = QImage(width, height, 32); // 32 Bit

    Sphere s(Point(0.0,0.0,-50.0), 40.0);
    shapes.push_back(&s);
    cout << shapes.size() <<endl;
}

【讨论】:

    【解决方案3】:

    引用:

    Sphere s(Point(0.0,0.0,-50.0), 40.0);
    shapes.push_back(&s);
    

    您将局部变量的地址放入全局集合中。两行后,s 超出范围,&amp;s 变为无效。

    【讨论】:

      【解决方案4】:

      问题是你的“createScene”函数:

      无效创建场景() { 图像 = QImage(宽度,高度,32); // 32 位 球体 s(Point(0.0,0.0,-50.0), 40.0); 形状.push_back(&s); cout

      对象s 已在“createScene”函数的堆栈帧中分配。它是一个局部变量,一旦“createScene”函数结束,它就会被破坏并失效。因此,您已将一个指向不存在对象的指针放入您的形状向量中。相反,您应该做的是在堆上分配一个 Shape 对象(也许将其存储在 boost::shared_ptr 中?)并将其放入向量中。

      【讨论】:

        【解决方案5】:

        显然你没有一个形状向量,而是一个指向形状的指针向量。在createScene 中,您将一个指向该向量的局部变量的指针添加到该向量中。当该方法完成时,该本地被销毁。当您稍后尝试调用该对象时,您会尝试调用一个不存在的对象。

        您可以通过使用boost::shared_ptr 作为向量的参数类型来解决该问题。

        // definition of you vector
        std::vector< boost::shared_ptr< Shape > > shapes;
        
        void createScene()
        {
        
            image = QImage(width, height, 32); // 32 Bit
        
            boost::shared_ptr< Shape >( new Sphere s(Point(0.0,0.0,-50.0), 40.0) );
            shapes.push_back(s);
            cout << shapes.size() <<endl;
        }
        

        更新: 如果容器应该实际拥有对象,您也可以使用 Boost.PointerContainer 代替智能指针。

        【讨论】:

        • 其实,如果你给本地创建一个boost::shared_ptr,本地还是会被销毁。
        • 嗯,有时你必须把它拼写得很清楚。当然,我不是这个意思,我现在添加的示例代码应该可以清楚地说明这一点。
        • @MSalters,它被分配了“新”。
        • 是的,新代码使 Sphere 不再是本地的。这是他需要做出的关键改变。 shared_ptr 并不重要,很简单。
        【解决方案6】:

        您的示例不会像这样编译。这个实现必须返回一个值:

        virtual bool checkIntersect(Point p, Point d, Point *temp) {};
        

        如果您的全局形状向量包含 NULL 指针,shapes.size() 将不为零,但 shapes[0]-&gt;checkIntersect 将失败。

        一般来说,使用调试器(gdb、Visual Studio)并单步调试您的代码。检查每个变量,您肯定会发现问题。

        【讨论】:

          【解决方案7】:
          void createScene()
          {
          
              image = QImage(width, height, 32); // 32 Bit
          
              Sphere s(Point(0.0,0.0,-50.0), 40.0);
              shapes.push_back(&s);
              cout << shapes.size() <<endl;
          }
          

          你的Sphere s(Point(0.0,0.0,-50.0), 40.0); 是一个局部变量,当CreateScene 结束时会被销毁。您将指向 s 的指针 &amp;s 推送到您的形状向量中,因此一旦 CreateScene 完成(即在上面的最后一个 cout 语句之后)shapes[0] 指向某个被破坏的对象。 改为:

          void createScene()
          {
          
              image = QImage(width, height, 32); // 32 Bit
          
              Sphere* s_p = new Sphere(Point(0.0,0.0,-50.0), 40.0);
              shapes.push_back(s_p);
              cout << shapes.size() <<endl;
          }
          

          不要忘记删除shapes 中的所有项目,然后再从shapes 中删除它们。

          【讨论】:

            猜你喜欢
            • 2011-08-02
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-09-26
            • 1970-01-01
            相关资源
            最近更新 更多