【问题标题】:C++/SDL Memory ManagementC++/SDL 内存管理
【发布时间】:2016-02-11 06:01:33
【问题描述】:

我正在开发一个简单的滚动空间射击游戏。我有一个由实体类对象继承的 Sprite 类。我从这些对象中得到内存泄漏。我用这个游戏的主菜单对此进行了测试,我相信问题出在 sprite 类中。

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

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

Sprite 类:

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 类。当不再需要它们时,我使用与此类似的代码来处理它们的删除:

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

Asteroid 类只是随机更改图像的类之一。它继承了 Entity,它继承了 Sprite。不确定它是否也会泄漏内存。很难用其他所有东西进行测试..

这里是小行星类:

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++ 新手,但学得很快。如果有人能指出我正确的方向,我将不胜感激。

谢谢

【问题讨论】:

    标签: c++ memory sdl


    【解决方案1】:

    问题是您的向量直接存储对象。因此,当对象被复制/移动时,它们会在不应该破坏纹理时破坏纹理。

    例如,我假设您尚未实现自定义复制构造函数...假设您有一个 std::vector&lt;Sprite&gt; 并且您正尝试向其中添加一个新对象,如下所示:

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

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

    尝试使用std::shared_ptrs 的向量来代替对象本身的向量。像这样:

    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 文档了解更多信息。

    【讨论】:

    • 新的堆栈溢出.. 抱歉重复的帖子.. 这就是我想说的:我肯定会研究共享指针,但我正在使用 emplace_back 将对象添加到向量中并给每个反对它自己的价值观。 idk 如果这有什么不同..我实际上已经用纹理管理器类“解决”了这个问题,但我仍然不是 100% 确定..当你说只有一个真实的对象而其他所有东西都引用它时,是这个类似于纹理/资源管理器?你怎么能引用一个对象,但让它同时占据多个位置?
    • 即使您使用 emplace_back 添加对象,随着向量的增长/缩小,它也会复制包含的对象。
    • 如何引用对象?例如与射弹碰撞。现在我将向量传递给函数,但到目前为止我无法使用 shared_ptr 来做到这一点
    猜你喜欢
    • 2010-09-06
    • 2018-12-17
    • 1970-01-01
    • 2014-10-24
    • 2020-01-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多