向量,“虚拟”,函数调用上的分段错误

时间:2009-12-07 09:52:41

标签: c++

尝试调用属于“Shape”指针向量的对象内的函数时,我遇到了分段错误

我的问题在于这个函数::

    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;
    }
};

7 个答案:

答案 0 :(得分:7)

问题在于:

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);

从堆中分配Sphere以使其保持不变。完成后请务必delete

答案 1 :(得分:4)

在向量形状中放置局部变量的地址。退出函数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;
}

答案 2 :(得分:3)

引用:

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

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

答案 3 :(得分:2)

显然你没有形状矢量,而是形状指针的矢量。在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而不是智能指针。

答案 4 :(得分: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;
}

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

答案 5 :(得分:0)

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

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

如果形状的全局向量包含NULL指针,shapes.size()将为非零,shapes[0]->checkIntersect将失败。

通常,使用调试器(gdb,Visual Studio)并逐步执行代码。检查每个变量,你一定会发现问题。

答案 6 :(得分:0)

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,指向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之前,请不要忘记删除{{1}}中的所有项目。

相关问题