2017-05-28 99 views
0

这是一个C++内存管理问题,因此我选择在这里提问。 我正在用SFML创建一个游戏。我之前使用过SDL,管理我的纹理非常简单,但SFML的工作方式不同。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*/ 

我面临的挑战是,在白色矩形的雪碧图像效果Character类使用SF ::纹理正在绘制。所以Character Sprite失去了它的纹理链接,而SFML只画了一个白色的矩形。为了解决这个问题,我创建了一个原始纹理指​​针并在Character构造函数中初始化它。这工作和雪碧绘制正确。

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

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

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

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

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

但这是错误明显。 我也尝试在main()结束时删除character.Texture,当我退出应用程序但也导致错误。

然后我试图做使用汉字的构造函数里面uinque_ptr:

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

,并由此得出一个漂亮的藏青色,黑色矩形,而不是雪碧纹理。我不知道如何或如果我可以声明,然后初始化unique_ptr。

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

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

+0

你没有给我们足够的代码来看看你做错了什么。这就是说,使用'unique_ptr'可能是一个好主意。如果你的纹理呈蓝色,那听起来像是一个初始化错误。另外,考虑使用'make_unique'而不是'unique_ptr <...> foo(new whatever)'。 – Rook

+0

你说过你以前的做法有问题......但从来没有问过*。您正在寻找解决方案来解决您甚至不应该拥有的问题。你应该问问关于你的第一个问题*的问题。 – nvoigt

回答

2

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

使用调试器断点来跟踪发生的情况。在Charactersf::Texture的析构函数中抛出一个中断点,并浏览启动和关闭序列。或使用日志打印消息,如:“Character ::〜called。”。


我想我的内存泄漏,如果是这样,我该如何正确使用智能指针或妥善管理自己的记忆?

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

从SFML文档:

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

直到你看到泄漏检测仪泄漏,你真的不能认为你正在泄漏内存。您可以将第三方内存追踪器添加到您的程序中。

再次,在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); 
    } 
} 

而且错误会很明显。

+0

我在Visual Studio 2013中使用MSVC++,我已经阅读了跟踪漏洞,但我想在编码狂欢之前确定。我已经编辑了我的问题来添加更多的细节,但从您的答案中,您似乎建议我应该停止担心删除原始指针,直到我有内存泄漏错误。 – zimspy