1


0

ベクトル、「仮想」、関数呼び出しでのセグメンテーション違反

「シェイプ」ポインターのベクトルの一部であるオブジェクト内の関数を呼び出そうとすると、セグメンテーションフォールトが発生します。

私の問題はこの関数にあります
    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;
    }

最初は、シェイプを1つだけ追加しています。

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

したがって、グローバルな「形状」のベクトルがあります。 ベクトル図形;

私はクラスの形をしています

#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
#include
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 Answer


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を割り当てて永続化する。 完了したら、必ず「削除」してください。


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


3


引用:

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

グローバルコレクションにローカル変数のアドレスを入れています。 2行後、「s」は範囲外になり、「&s」は無効になります。


2


どうやら、図形のベクトルではなく、図形へのポインターのベクトルがあります。 「createScene」では、ローカル変数へのポインターをそのベクターに追加します。 メソッドが終了すると、そのローカルは破棄されます。 後でオブジェクトで呼び出しを行おうとすると、存在しないオブジェクトで呼び出しを行おうとします。

この問題は、ベクトルの引数タイプとしてhttp://www.boost.org/doc/libs/1_41_0/libs/smart_ptr/smart_ptr.htm[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() <
  • UPDATE:*スマートポインターの代わりにhttp://www.boost.org/doc/libs/1_41_0/libs/ptr_container/doc/ptr_container.html[Boost.PointerContainer]を使用することもできます(コンテナが想定されている場合)実際にオブジェクトを所有します。


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

The object s has been allocated within the stack frame of the "createScene" function. It is a local variable, and it will be destructed and invalidated as soon as the "createScene" function ends. Therefore, you have put a pointer to a non-existent object into your shapes vector. What you should do, instead, is allocate a Shape object on the heap (perhaps storing it in a boost::shared_ptr?) and put that in the vector.


0


あなたの例はこのようにはコンパイルされません。 この実装は値を返す必要があります:

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

図形のグローバルベクトルにNULLポインターが含まれている場合、 `shapes.size()`はゼロ以外になりますが、 `shapes [0]→ checkIntersect`は失敗します。

一般に、デバッガー(gdb、Visual Studio)を使用して、コードをステップ実行します。 すべての変数を確認すると、問題が確実に見つかります。


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

あなたの 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() <

また、「shapes」から削除する前に、「shapes」内のすべてのアイテムを削除することを忘れないでください。