0

SDL を使用して、非常に単純な Pong ゲームを作成しています。衝突検出のために、次のような DetectCollision というクラスがあります。

class DetectCollision {
    public:
        std::vector<Object*> objects;
        int numOfObjects;

        DetectCollision();
        ~DetectCollision();

        void takeObjs(Object &);
        void handleCollision();
};

つまり、takeObjs(Object &) 関数は Object クラスのオブジェクトを取得し、それをベクトルに格納します。takeObjs(Object &) は次のようになります。

void DetectCollision::takeObjs(Object &obj1){
    objects.push_back(&obj1);
}

すべてがこの時点まで機能します。ベクトル「オブジェクト」にアクセスしてすべての衝突を検出でき、問題なく動作しますが、ベクトルを削除しようとすると問題が発生します。私が間違っていなければ、それはポインタのベクトルです。したがって、それを削除するために行ったことは、クラス デストラクタにあります。

DetectCollision::~DetectCollision(){
    for (unsigned int i = 0; i < objects.size(); ++i){
        delete objects[i];
    }
    objects.clear();
}

GCC コンパイラを使用する Code::Blocks IDE によると、「delete objects[i];」でセグメンテーション違反が発生します。ライン。また、プログラムの別の部分で、クラスが保持するスキンを SDL_FreeSurface() しようとする segfault が発生しますが、これは簡単に修正できると思います。このベクトルが主な問題です。問題の修正方法を知るために完全なソース コードを確認する必要がある場合は、提供できます。どんな援助にもとても感謝しています。ありがとう、DFTBA!

4

3 に答える 3

0

潜在的な問題の 1 つは、 Rule of ThreeDetectCollisionに違反することです。インスタンスがコピーされた場合、コピーは同じポインターのベクトルを取得し、最終的に double になります。Objectdelete

于 2013-03-23T17:31:22.997 に答える
0

デストラクタが呼び出されたときにオブジェクトが存在しなくなったため、アプリのセグメンテーション違反。

このtakeObjsメソッドは、オブジェクトへの参照を受け取り、そのオブジェクトへのポインターをベクター内に格納します。そのオブジェクトは別の場所で定義されています。そのオブジェクトがスコープ外になると、自動的に破棄されます。

デストラクタに到達するまでに、オブジェクトは破棄されます。アプリを再度破棄しようとしているため、アプリのセグメンテーション違反が発生します。

C++ でのオブジェクトのスコープについて読む必要があり (この質問への回答を読んでください) 、C++ でのオブジェクトの破壊についても読む必要があります。

EDIT:クラッシュを説明するために短い例を追加

#include <iostream>
#include <vector>
using namespace std;

class Object {
public:
    int a;
    int b;

    Object(int a, int b)
    {
        this->a=a;
        this->b=b;
    }
};

class Test
{
    std::vector<Object*> objects;
public:
    Test(){}

    void Add(Object &obj)
    {
        objects.push_back(&obj);
    }

    void Print()
    {
        for(unsigned int i=0;i<objects.size();i++)
        {
            cout<<objects[i]->a<<" "<<objects[i]->b<<endl;
        }
    }

    ~Test()
    {
        for (unsigned int i = 0; i < objects.size(); ++i){
            delete objects[i];
        }
        objects.clear();
    }
};

void AddNewObjects(Test &t)
{
    Object x(1,2);
    Object y(3,4);
    t.Add(x);
    t.Add(y);
    // you can access your objects here
    t.Print();
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test t;
    AddNewObjects(t);
    // but if you try to access the objects here, you get a crash
    // because the objects were destroyed when exiting "AddNewObjects"
    t.Print();
    return 0;
    // your destructor tries to access the objects here (in order to destroy them)
    // and that's why it crashes
}

問題を解決するために使用できる 1 つの解決策を次に示します。

#include <iostream>
#include <vector>
using namespace std;

class Object {
public:
    int a;
    int b;

    Object(int a, int b)
    {
        this->a=a;
        this->b=b;
    }
};

class Test
{
    std::vector<Object*> objects;
public:
    Test(){}

    void Add(Object *pObj)
    {
        objects.push_back(pObj);
    }

    void Print()
    {
        for(unsigned int i=0;i<objects.size();i++)
        {
            cout<<objects[i]->a<<" "<<objects[i]->b<<endl;
        }
    }

    ~Test()
    {
        for (unsigned int i = 0; i < objects.size(); ++i){
            delete objects[i];
        }
        objects.clear();
    }
};

void AddNewObjects(Test &t)
{
    Object* x = new Object(1,2);
    Object* y = new Object(3,4);
    t.Add(x);
    t.Add(y);
    // you can access your objects here
    t.Print();
}

int _tmain(int argc, _TCHAR* argv[])
{
    Test t;
    AddNewObjects(t);
    // you can also access the objects here
    // because they are not destroyed anymore when exiting "AddNewObjects"
    t.Print();
    return 0;
}
于 2013-03-23T17:32:49.587 に答える
0

DetectCollision クラスに渡されたオブジェクトが別の場所で削除されているため、二重削除が発生している可能性があります。おそらくスコープ外にあるためです。

誰がオブジェクトを「所有」するかを考える必要があります。所有者のみがそれらを削除する必要があります。

于 2013-03-23T17:33:01.570 に答える