【问题标题】:SFML Texture memory managementSFML 纹理内存管理
【发布时间】:2017-05-28 08:19:52
【问题描述】:

这是一个 C++ 内存管理问题,因此我选择在这里提问。 我正在用 SFML 创建游戏。我以前使用过 SDL,管理我的纹理非常简单,但 SFML 的工作方式不同。

我的项目设置是这样的:

class Game
//create window and initialize game stuff

class Character
/*initializes its own textures and is also responsible for updating itself
as well as drawing itself*/

int main()
/*create an instance of Game -> Create an instance of Character and
runGame. I will implement the drawing and updating properly when I 
implement a scene graph and scene nodes but for now updating and drawing is 
done via global functions called by the Game Class*/

我面临的挑战是在角色类中为 Sprite 图像使用 sf::Texture 会导致绘制一个白色矩形。所以 Character Sprite 失去了它的 Texture 链接,SFML 只是绘制了一个白色的矩形。为了解决这个问题,我创建了一个原始纹理指​​针并在 Character 构造函数中对其进行初始化。这有效,Sprite 绘制正确。

//inside character.hpp
sf::Texture *texture;

//in Character constructor
texture= new (sf::Texture);

这意味着我必须管理内存并且代码感觉很难看。

我已经尝试这样做来管理分配的内存(我认为)以防止内存泄漏:

Character::~Character()
{ delete texturePtr; }

但这显然是错误的。 当我退出应用程序时,我还尝试在 main() 末尾删除 character.Texture ,但这也会导致错误。

然后我尝试在 Character 构造函数中使用 uinque_ptr:

std::unique_ptr<sf::Texture> texture(new sf::Texture);
//load Texture from Resource Manager instance

这将绘制一个漂亮的海军蓝黑色矩形而不是 Sprite 纹理。我不确定如何或是否可以声明然后初始化一个 unique_ptr。

我认为我正在泄漏内存,如果是,我该如何正确使用智能指针或正确管理我自己的内存?

当我意识到我说得含糊不清时,我添加了更多细节和代码。此外,我正在查询纹理并使用它来设置 Sprite Rect 尺寸,因此它肯定会被加载,但为了安全起见,我有一个记录器函数来检查我调用的任何资源是否已加载。

【问题讨论】:

  • 你没有给我们足够的代码来看看你做错了什么。也就是说,使用unique_ptr 可能是个好主意。如果你的纹理是蓝色的,这听起来像是一个初始化错误。另外,请考虑使用make_unique 而不是unique_ptr&lt;...&gt; foo(new whatever)
  • 你说你以前的做法有问题...但从来没有问过。您正在寻找一个您甚至不应该遇到的问题的解决方案。你应该问关于你的第一个问题的问题白色精灵。
  • 不要在这里使用'new',也不要使用指针。见官方例子sfml-dev.org/tutorials/2.5/graphics-sprite.php

标签: c++ memory-leaks sfml


【解决方案1】:

如果sf::TextureCharacter 的成员,那么它不会超出范围,直到您的Character 实例超出范围。

使用调试器断点来跟踪发生的情况。在Charactersf::Texture 的析构函数中抛出一个断点,并遍历您的启动和关闭序列。或者使用 Log 打印消息,例如:“Character::~ called.”


我认为我正在泄漏内存,如果是,我该如何正确使用智能指针或正确管理我自己的内存?

质疑所有假设,包括您正确加载纹理的假设。在您在屏幕上看到纹理绘制之前,您没有证据表明您已经加载了它。 (除非你想要一个深蓝色的矩形。我不知道你想画什么。我假设是一个角色精灵。)

来自 SFML 文档:

loadFromFile 函数有时会在没有明显原因的情况下失败。首先,检查 SFML 打印到标准输出的错误消息(检查控制台)。如果消息无法打开文件,请确保工作目录(任何文件路径都将被解释为相对的目录)是您认为的:当您从桌面环境运行应用程序时,工作目录是可执行文件夹。但是,当您从 IDE(Visual Studio、Code::Blocks、...)启动程序时,有时可能会将工作目录设置为项目目录。这通常可以在项目设置中很容易地更改。

除非您在泄漏检测器中发现泄漏,否则您真的不能假设您正在泄漏内存。您可以将第 3 方记忆追踪器添加到您的程序中。

再次,在sf::Texture 析构函数中使用调试断点来停止执行并查看您要解除分配的确切位置(如果这是问题所在)。


你真的应该阅读并关注Minimal, Complete, and Verifiable example。据我们所知,您可能会这样做:

class Character{
    sf::Sprite mySprite;

    public:
    Character(){
        sf::texture aTex;
        aTex.loadFromFile("c:\users\noob\Desktop\myawesomegame\stripper.png");

        mySprite.setTexture(aTex);
    }
}

// attempt 2
class Character{
    sf::Sprite mySprite;

    public:
    Character(){
        std::unique_ptr<sf::Texture> texture(new sf::Texture);
        texture->loadFromFile("c:\users\noob\Desktop\myawesomegame\stripper.png");

        mySprite.setTexture(*texture);
    }
}

而且错误会很明显。

【讨论】:

  • 我在 Visual Studio 2013 中使用 MSVC++,我已经阅读了跟踪泄漏的信息,但我想在开始编码狂潮之前确定一下。我已经编辑了我的问题以添加更多细节,但是从您的回答中,您似乎建议我应该停止担心删除 Raw 指针,直到出现内存泄漏错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-17
  • 2014-08-13
  • 2018-04-21
  • 1970-01-01
  • 1970-01-01
  • 2022-08-14
相关资源
最近更新 更多