C++/SDL 内存管理

C++/SDL Memory Management

我正在开发一个简单的滚动 space 射击游戏。我有一个 Sprite class 被 Entity Class 对象继承。我从这些对象中获取内存泄漏。我用这个游戏的主菜单测试了这个,我相信问题出在 sprite class 上。

内存问题似乎是我没有SDL_Destroy..ing 纹理和渲染器。然而,通过破坏纹理,我得到了一个纹理被另一个纹理替代的疯狂结果,或者根本没有纹理。如果我销毁渲染器,则不会加载任何图像。如果我两者都没有销毁,那么一切都可以正常加载,但存在内存泄漏。

我相信狂野的纹理与我处理对象矢量的方式有关,但我不知道另一种处理它们的方式..

雪碧class:

Sprite::Sprite()
{
}

Sprite::Sprite(SDL_Renderer* pRenderer, std::string filePath, int x, int y, int w, int h)
{
_renderer = pRenderer;
_filePath = filePath;

_image = IMG_LoadTexture(_renderer, filePath.c_str());

_rect.x = x;
_rect.y = y;
_rect.w = w;
_rect.h = h;
}

Sprite::~Sprite()
{
std::cout<<_filePath<<" destroyed"<<std::endl;
SDL_DestroyTexture(_image);
//SDL_DestroyRenderer(_renderer);

}
void Sprite::draw()
{
SDL_RenderCopy(_renderer, _image, NULL, &_rect);
}

我有几个矢量可以产生子弹、小行星等。它们都使用 Sprite class。当不再需要它们时,我使用类似的代码来处理它们的删除:

if (!update)
{
     vector[i] = vector.back;
     vector.pop_back;
}

小行星 class 只是随机更改图像的 classes 之一。它继承了 Entity,而 Entity 又继承了 Sprite。不确定它是否也在泄漏内存。很难用其他一切来测试..

这是小行星 class:

Asteroid::Asteroid(SDL_Renderer* pRenderer) :

_health(50)
{
_renderer = pRenderer;

_posX = getRandom(800);
_posY = -50;
_width = 30;
_height = 30;

_velocityX = getRandom(2);
_velocityY = getRandom(2);

initSprite(pRenderer, "Asteroid.png", _posX, _posY, _width, _height);

 }

Asteroid::~Asteroid()
{

//EMPTY
}

bool Asteroid::update(std::vector<Bullet>& bullets,
                  std::vector<Block>& blocks)
{
//COLLISION BULLET
for (int i = 0; i < bullets.size(); i++)
{
    if (collisionCheck(bullets[i].getRect()))
    {
        //CHANGE VELOCITY & POSITION
        _velocityY -= 0.2f;

        _posY -= 3;

        //TAKE DAMAGE
        _health -= 10;
    }
}

if(_posY >= 500)
{
    return false;
}

//IF DEAD
if (_health <= 0)
{
    return false;
}

//MOVEMENT
drift();

return true;
}

void Asteroid::draw()
{
Entity::draw();
}

void Asteroid::drift()
{
//move position
_posX += _velocityX;
_posY += _velocityY;

//check boundaries
if (_posY > 0) {
    if (_posX < 0)
    {
        _velocityX *= -1;
    }
    if (_posX > 800 - _width)
    {
        _velocityX *= -1;
    }
    if (_posY < 0)
    {
     _velocityY *= -1;
    }
    if (_posY > 600 - _height)
    {
        _velocityY *= -1;
    }
}

}

bool Asteroid::collisionCheck(SDL_Rect rect2)
{
return !(_rect.x > rect2.x + rect2.w || _rect.x + _rect.w < rect2.x ||
         _rect.y > rect2.y + rect2.h || _rect.y + _rect.h < rect2.y );
}

int Asteroid::getRandom(int threshold)
{
 _randomNumber = rand() % threshold + 1;

return _randomNumber;}

我是 C++ 的新手,但学得很快。如果有人能指出我正确的方向,我将不胜感激。

谢谢

问题是您的向量直接存储对象。因此,当物体在 copied/moved 周围时,它们会在不应该的时候破坏纹理。

例如,我假设您还没有实现自定义复制构造函数...假设您有一个 std::vector<Sprite> 并且您正在尝试向其中添加一个新对象,如下所示:

{
  Sprite s(renderer, "image.png", 0, 0, 100, 100);
  sprites.push_back(s);
}

当您这样做时,s 将加载纹理。当你把它推到 sprites 向量上时,它会创建一个 s 的副本(所以现在它们都有相同的 _image 值)。然后在下一行(当 s 超出范围时),s 将破坏纹理——但 sprites 向量中的副本仍在尝试引用它!

与其使用对象本身的矢量,不如尝试使用 std::shared_ptr 的矢量。像这样:

std::vector<std::shared_ptr<Sprite> > sprites;
std::shared_ptr<Sprite> s(new Sprite(renderer, "image.png", 0, 0, 100, 100));
sprites.push_back(s);

这样只复制指针,真正的对象只有一个(无人引用时会自动删除)

查看 std::shared_ptr 文档了解更多信息。