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() 类持有的皮肤,但我认为我可以很容易地修复这个问题。这个向量是主要问题。如果您需要查看完整的源代码以帮助我了解如何解决问题,我可以提供。我非常感谢任何帮助。感谢和 DFTBA!

4

3 回答 3

0

一个潜在的问题是DetectCollision违反了三法则。如果复制了一个实例,则该副本将获得相同Object指针的向量,最终导致 double deletes。

于 2013-03-23T17:31:22.997 回答
0

您的应用程序出现段错误,因为调用析构函数时对象不再存在。

takeObjs方法接收对对象的引用,然后将指向该对象的指针存储在向量中。该对象在其他地方定义。当该对象超出范围时,它会自动销毁。

当您到达析构函数时,该对象已被销毁。该应用程序出现段错误,因为您试图再次销毁它。

您应该阅读 C++ 中对象的范围(阅读此问题的答案),还应该阅读C++ 中的对象破坏

编辑:添加简短示例来说明崩溃

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

这是您可以用来解决问题的一种解决方案:

#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 回答