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
文档了解更多信息。
我正在开发一个简单的滚动 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
文档了解更多信息。