c++ - 使用 TTF 释放表面和破坏纹理后,SDL2 内存使用量并未完全减少
问题描述
自从我开始使用 SDL_TTF 以来就一直在发生这种情况,但我找不到它的原因。当我创建一个文本对象时,程序永远处于 x 内存使用量,直到我做某事(那里没有错)。然后当我添加文本时,程序内存使用量会增加。那里也没有错。但是,当我决定删除文本时,首先,由于某种原因,程序的 ram 使用量从它所在的位置增加,然后按应有的方式减少,但是它永远不会减少到使用相同文本之前的状态。如果我不断重复添加和减去文本,内存只会慢慢上升。
这就是我的意思:
添加文本后
删除文本后
如果照片中不清楚,则程序从 102.8mb 内存使用开始。添加文本时,它会跳转到 104mb,然后在删除文本后,程序会回到 103.6mb 的使用量。到底是什么在使用额外的兆字节内存???
这是我的 Text 对象代码,以及在函数中调用它的位置。
文本.h
#ifndef TEXT_H
#define TEXT_H
#include <SDL2/SDL_ttf.h>
#include <SDL2/SDL.h>
#include "events.h"
#include <iostream>
#include <string>
#include <vector>
using std::vector;
using std::string;
using std::cout;
using std::endl;
using std::exception;
class Text
{
public:
Events EVENTS;
Text(void);
///Public variables
static vector <TTF_Font*> fonts;
const int lowestFontSize = 1;
const int highestFontSize = 100;
int fontIndex;
int textSize;
SDL_Rect textRect;
int x;
int y;
int initialX, initialY;
bool setup;
static int numOfInstances;
///Functions
void Setup(SDL_Renderer *renderer, string txt, int x, int y, int txtSize, SDL_Color Colour = {0,0,0}, bool isBold = false, string fontType = "arial.ttf", bool isWrapped=false, int theWrapWidth=0);
string Get_Text();
void Change_Text(SDL_Renderer *renderer, string newText);
void Draw_Text(SDL_Renderer *renderer);
void Change_Position(SDL_Renderer *renderer, int xPos, int yPos);
void Change_Position_And_Text(SDL_Renderer *renderer, int xPos, int yPos, string newText);
int Text_Width(int FirstCharIndex, int numOfCharsPastFirstIndex);
int Text_Height(int FirstCharIndex, int numOfCharsPastFirstIndex);
void Free_All();
private:
///SDL stuff
SDL_Texture *textTexture;
SDL_Surface *textSurface;
SDL_Color colour;
SDL_Point point;
///text varibales
string text;
int textW;
int textH;
bool bold;
bool wrapped;
int wrappedWidth;
};
#endif
文本.cpp
#include "text.h"
int Text::numOfInstances = 0;
vector <TTF_Font*> Text::fonts;
Text::Text()
{
setup = false;
textTexture = NULL;
textSurface = NULL;
}
void Text::Setup(SDL_Renderer *renderer, string txt, int xPos, int yPos, int txtSize, SDL_Color Colour, bool isBold, string fontType, bool isWrapped, int theWrapWidth )
{
if (setup == false){
numOfInstances += 1;
wrapped = isWrapped;
wrappedWidth = theWrapWidth;
text = txt;
textSize = txtSize;
bold = isBold;
colour = Colour;
textW = 0;
textH = 0;
x = xPos;
y = yPos;
initialX = x;
initialY = y;
fontIndex = textSize-lowestFontSize -1;
///One time setups
if (numOfInstances == 1){
try{
TTF_Init();
//cout << "Initialised ttf" << endl;
}
catch (exception &err){
cout << "Could not initialise ttf for text \"" << text << "\". Error from SDL is: " << TTF_GetError() << ". Error from C++ is: " << err.what() << endl;
}
for (int i=lowestFontSize; i <= highestFontSize; i++){
TTF_Font *currentFont = TTF_OpenFont(fontType.c_str(), i);
if (!currentFont){
cout << "Error with font in text \"" << txt << "\" Error is: " << SDL_GetError() << endl;
}
//TTF_SetFontKerning(currentFont, 0);
fonts.push_back(currentFont);
}
}
if (bold == true){
TTF_SetFontStyle(fonts[fontIndex], TTF_STYLE_BOLD);
}
if (!SDL_SetHint( SDL_HINT_RENDER_SCALE_QUALITY, "2" ) ){ ///2 is highest
cout << "Text rendering quality not enabled " << text << endl;
}
if (text != ""){ ///Only create textures if there is text
if (wrapped == true){
textSurface = TTF_RenderText_Blended_Wrapped(fonts[fontIndex], text.c_str(), colour, wrappedWidth); ///Recreate the textures/surfaces
}
else{
textSurface = TTF_RenderText_Blended(fonts[fontIndex], text.c_str(), colour); ///Recreate the textures/surfaces
}
if (!textSurface){
cout << "Unable to create surface of text " << text << " error is: " << SDL_GetError() << endl;
}
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
if (!textTexture){
cout << "Unable to create texture from surface of text " << text << " error is: " << SDL_GetError() << endl;
}
SDL_FreeSurface(textSurface);
textSurface = NULL;
SDL_QueryTexture(textTexture, NULL, NULL, &textW, &textH);
textRect = {x, y, textW, textH};
}
point = {0, 0};
setup = true;
}
else{
//cout << "Trying to setup a text already setup! " << text << endl;
}
}
void Text::Change_Position_And_Text(SDL_Renderer *renderer, int xPos, int yPos, string newText )
{
if (setup == true){
text = newText;
x = xPos;
y = yPos;
textRect.x = x;
textRect.y = y;
if (textTexture != NULL){
SDL_DestroyTexture(textTexture); ///Free memory not going to be used again.
textTexture = NULL;
}
if (wrapped == true){
textSurface = TTF_RenderText_Blended_Wrapped(fonts[fontIndex], text.c_str(), colour, wrappedWidth); ///Recreate the textures/surfaces
}
else{
textSurface = TTF_RenderText_Blended(fonts[fontIndex], text.c_str(), colour); ///Recreate the textures/surfaces
}
if (!textSurface){
cout << "Unable to create surface of text " << text << " error is: " << SDL_GetError() << endl;
}
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
if (!textTexture){
cout << "Unable to create texture from surface of text " << text << " error is: " << SDL_GetError() << endl;
}
SDL_FreeSurface(textSurface);
textSurface = NULL;
SDL_QueryTexture(textTexture, NULL, NULL, &textW, &textH); ///neeed this
textRect = {x, y, textW, textH};
}
}
void Text::Change_Position(SDL_Renderer *renderer, int xPos, int yPos)
{
if (setup == true){
x = xPos;
y = yPos ;
textRect.x = xPos;
textRect.y = yPos;
}
}
void Text::Change_Text(SDL_Renderer *renderer, string newText)
{
if (setup == true){
text = newText;
if (textTexture != NULL){
SDL_DestroyTexture(textTexture); ///Free memory not going to be used again.
textTexture = NULL;
}
if (text != ""){
if (wrapped == true){
textSurface = TTF_RenderText_Blended_Wrapped(fonts[fontIndex], text.c_str(), colour, wrappedWidth); ///Recreate the textures/surfaces
}
else{
textSurface = TTF_RenderText_Blended(fonts[fontIndex], text.c_str(), colour); ///Recreate the textures/surfaces
}
if (!textSurface){
cout << "Unable to create surface of text " << text << " error is: " << SDL_GetError() << endl;
}
textTexture = SDL_CreateTextureFromSurface(renderer, textSurface);
if (!textTexture){
cout << "Unable to create texture from surface of text " << text << " error is: " << SDL_GetError() << endl;
}
SDL_FreeSurface(textSurface);
textSurface = NULL;
SDL_QueryTexture(textTexture, NULL, NULL, &textW, &textH); ///neeed this
textRect = {x, y, textW, textH};
}
}
}
int Text::Text_Width(int FirstCharIndex, int numOfCharsPastFirstIndex)
{
int w,h;
string textSelection = text.substr(FirstCharIndex, numOfCharsPastFirstIndex);
TTF_SizeText(fonts[fontIndex], textSelection.c_str(), &w, &h);
return w;
}
int Text::Text_Height(int FirstCharIndex, int numOfCharsPastFirstIndex)
{
int w,h;
string textSelection = text.substr(FirstCharIndex, numOfCharsPastFirstIndex);
TTF_SizeText(fonts[fontIndex], textSelection.c_str(), &w, &h);
return h;
}
string Text::Get_Text()
{
if (setup == true){
return text;
}
else{
return "";
//cout << "Text not setup when trying to obtain text through Get_Text() function" << endl;
}
}
void Text::Draw_Text(SDL_Renderer *renderer)
{
if (setup == true){
//cout << numOfInstances << endl;
if (SDL_PointInRect(&EVENTS.mousePos, &textRect) && EVENTS.currentCursor != SDL_SYSTEM_CURSOR_IBEAM){
EVENTS.Change_Cursor(SDL_SYSTEM_CURSOR_IBEAM);
}
SDL_RenderCopy(renderer, textTexture, NULL, &textRect);
}
else{
//cout << "Text not setup when trying to draw it in Draw_Text() function" << endl;
}
}
void Text::Free_All()
{
if (setup == true){
if (textSurface == NULL){
//cout << "Text surface already free'd" << endl;
}
else{
SDL_FreeSurface(textSurface);
textSurface = NULL;
//cout << "Free'd surface \n";
}
if (textTexture == NULL){
//cout << "Could not free memory for text \"" << text << "\". Error from SDL is: " << TTF_GetError() << endl;
}
else{
SDL_DestroyTexture(textTexture);
textTexture = NULL;
}
if (numOfInstances == 1){
for (int i=0; i <= (highestFontSize-lowestFontSize); i++){
TTF_CloseFont(fonts[i]);
//cout << "Closed " << lowestFontSize+i << endl;
}
try{
TTF_Quit();
//cout << "Quit ttf" << endl;
}
catch (exception &err){
cout << "Could not quit ttf for text \"" << text << "\". Error from SDL is: " << TTF_GetError() << ". Error from C++ is: " << err.what() << endl;
}
}
///For TTF_Init();
numOfInstances -= 1;
//cout << "Free'd " << text << endl;
}
else{
//cout << "Text not setup yet when trying to free!" << endl;
}
setup = false;
}
我用来显示文本的功能:
void Test::Setup(SDL_Renderer *renderer)
{
if (setup == false){
setup = true;
testText.Setup(renderer, "", 300, 200, 30);
}
}
void Test::Tester(SDL_Renderer *renderer)
{
Setup(renderer);
if (EVENTS.currentKey != ""){
testText.Change_Text(renderer, testText.Get_Text() + EVENTS.currentKey);
}
if (EVENTS.pasteText == true){
testText.Change_Text(renderer, testText.Get_Text() + SDL_GetClipboardText());
}
if (EVENTS.backspacePressed == true){
if (testText.Get_Text() != "") {
string tempText = (testText.Get_Text());
tempText.pop_back();
testText.Change_Text(renderer, tempText);
}
}
testText.Draw_Text(renderer);
}
解决方案
推荐阅读
- dialogflow-es - Google 上的帐户关联操作
- linux - 如何解决 Cron 作业中的预期 EOF
- indexing - RavenDB:如何从 MultiMapIndex 中正确查询/过滤嵌套值?
- reactjs - 在 recharts 中有条件地将边界半径放在 Bar 上
- flutter - 导航到其他页面时保留按钮的状态
- iis - 是否可以使用 IIS 重写模块在服务器而不是客户端上重写 URL
- asp.net - 网格视图内的网格视图 网格视图内的网格视图
- bootstrap-4 - Bootstrap 侧视图在小屏幕中移至底部
- c# - 关于在 C# 中获取后台进程
- python - 检查一个基本的python函数