SFML 纹理内存管理
SFML Texture memory management
这是一个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*/
我面临的挑战是,在角色 class 中使用 sf::Texture 作为 Sprite 图像会导致绘制一个白色矩形。所以 Character Sprite 失去了它的 Texture link 而 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 尺寸,因此肯定会加载它,但为了安全起见,我有一个记录器函数来检查我调用的任何资源是否已加载。
如果 sf::Texture
是 Character
的成员,那么它将 不会 超出范围,直到您的 Character
实例超出范围。
使用调试器断点跟踪发生的情况。在 Character
和 sf::Texture
的析构函数中放置一个断点,然后遍历启动和关闭序列。或者使用 Log 打印消息,例如:"Character::~ called."
I think I am leaking memory and if so, how do I correctly use the smart pointers or manage my own memory properly?
质疑所有假设,包括您正确加载纹理的假设。在您看到纹理在屏幕上绘制之前,您没有证据表明您已经加载了它。 (除非你想要一个海军蓝色的矩形。我不知道你想画什么。我假设是一个角色精灵。)
来自 SFML 文档:
The loadFromFile function can sometimes fail with no obvious reason. First, check the error message that SFML prints to the standard output (check the console). If the message is unable to open file, make sure that the working directory (which is the directory that any file path will be interpreted relative to) is what you think it is: When you run the application from your desktop environment, the working directory is the executable folder. However, when you launch your program from your IDE (Visual Studio, Code::Blocks, ...) the working directory might sometimes be set to the project directory instead. This can usually be changed quite easily in the project settings.
除非您在泄漏检测器中看到泄漏,否则您真的不能认为您正在泄漏内存。您可以将第 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);
}
}
而且错误很明显。
这是一个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*/
我面临的挑战是,在角色 class 中使用 sf::Texture 作为 Sprite 图像会导致绘制一个白色矩形。所以 Character Sprite 失去了它的 Texture link 而 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 尺寸,因此肯定会加载它,但为了安全起见,我有一个记录器函数来检查我调用的任何资源是否已加载。
如果 sf::Texture
是 Character
的成员,那么它将 不会 超出范围,直到您的 Character
实例超出范围。
使用调试器断点跟踪发生的情况。在 Character
和 sf::Texture
的析构函数中放置一个断点,然后遍历启动和关闭序列。或者使用 Log 打印消息,例如:"Character::~ called."
I think I am leaking memory and if so, how do I correctly use the smart pointers or manage my own memory properly?
质疑所有假设,包括您正确加载纹理的假设。在您看到纹理在屏幕上绘制之前,您没有证据表明您已经加载了它。 (除非你想要一个海军蓝色的矩形。我不知道你想画什么。我假设是一个角色精灵。)
来自 SFML 文档:
The loadFromFile function can sometimes fail with no obvious reason. First, check the error message that SFML prints to the standard output (check the console). If the message is unable to open file, make sure that the working directory (which is the directory that any file path will be interpreted relative to) is what you think it is: When you run the application from your desktop environment, the working directory is the executable folder. However, when you launch your program from your IDE (Visual Studio, Code::Blocks, ...) the working directory might sometimes be set to the project directory instead. This can usually be changed quite easily in the project settings.
除非您在泄漏检测器中看到泄漏,否则您真的不能认为您正在泄漏内存。您可以将第 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);
}
}
而且错误很明显。