SDL2 Memory Leaks C++ - c++

So when I run the app, at the biginning every thing runs smooth, but the more it goes, the slower it is. I looked at the memory it was using and when it reaches 400 mb it completely stops for 30 secs and then drop back to 200.
I am pretty new to SDL2, and I assume it is because each frame I call:
optionsTS = TTF_RenderText_Blended(font, "Options.", blanc);
optionsT = SDL_CreateTextureFromSurface(renderer, optionsTS);
for example and I have plenty of them.
The problem is that I don't know how to delete properly the object each frame, because if I do a SDL_FreeSurface I get an error.
I won't publish my whole code because it's a mess, but if you want it, feel free to ask.
Do you know how to fix that?

Just thought I would turn my comment into an answer.
In your code you call
optionsTS = TTF_RenderText_Blended(font, "Options.", blanc);
optionsT = SDL_CreateTextureFromSurface(renderer, optionsTS);
every frame, I suspect that if you remove them from there, initialise them outwith of the render loop and simply pass them in as arguments, you should lose the memory leak: the reason being that you will create only one in-memory instance of each and then you can repeatedly use them as needed. On looking at it again, I suspect that you could destroy optionTS once you have made optionT, that way you will save even more memory. (not tested yet as my main machine just crashed this weekend, and I am still re-installing drivers and VS2010)
As a general rule, try and not create/destroy any objects in the render loop, tends to get big and messy fast.

Consider taking advantage of RAII in C++ if possible.
For example, create a class that wraps an SDL_Surface and calls SDL_FreeSurface in the destructor.
class MySurface
{
public:
MySurface(SDL_Surface & surface) : m_surface(surface) {}
~MySurface() {SDL_FreeSurface(m_surface);}
SDL_Surface & GetSDLSurface() {return m_surface;}
private:
SDL_Surface & m_surface;
};
You would then create an instance of MySurface every time you grabbed an SDL_Surface from the SDL API, and you won't have to worry about when or whether to free that surface. The surface will be freed as soon as your instance of MySurface goes out of scope.
I'm certain better implementations can be written and tailored to your needs, but at a minimum something similar to this may prevent you from having leaks in the future.

Related

QGraphicsItem is not visible after adding to scene

I'm working on a diagram visualisation tool and I ran into an issue where my QGraphicsScene does not display a shared_ptr<DiagramItem> when a raw pointer obtained via .get() is passed to scene->addItem().
Subsequent check via scene->items() shows that my DiagramItem is not a part of the scene. My guess is that it got freed as the refcounter on the shared_ptr will be zero after leaving the scope of the testing function...
But that was the testing case. In my actual code I'm using a shared_ptr that I got from elsewhere and is definitely present in memory with a non-zero refcounter. I get the raw pointer of that and pass it to scene->addItem(). It is also not displayed, but this time it is present in scene->items(). So why is it not being drawn?
If I switch from using shared_ptr<DiagramItem> to DiagramItem* then the issue disappears and everything is displayed properly. But due to limitations from the rest of the project, I cannot easily abandon smart pointers here, nor do I want to.
Did I run into some kind of memory limitation or am I doing something wrong?
I already tried calling show() and update() on the item and increasing the scene size in case the item doesn't fit (it does). I also tried breakpointing the paint() method, but that one doesn't get called at all.
I found a possibly related question here where similar behaviour occurs due to the object going out of scope and being deallocated, but that doesn't seem to be the case with my actual DiagramItem.
class DiagramItem : public QGraphicsItem
{
...
}
//Create scene
auto scene = new QGraphicsScene(nullptr);
//Item is created OR obtained from elsewhere
auto item1 = std::make_shared<DiagramItem>(nullptr, QString("aaa"), true);
auto item2 = GetDiagramItem(...);
//Raw pointers get passed to addItem
scene->addItem(item1.get());
scene->addItem(item2.get());
//Item1 is not present at all (directly created DiagramItem)
//Item2 is present but invisible (DiagramItem passed from elsewhere)
//myItem gets Item2
auto myItem = scene->items()[0];
...

Crash after QGraphicsScene::removeItem() with custom item class

I am populating a QGraphicsScene with instances of a custom item class (inherting QGraphicsPathItem). At some point during runtime, I try to remove an item (plus its children) from the scene by calling:
delete pItem;
This automatically calls QGraphicsScene::removeItem(), however it also leads to a crash in the class QGraphicsSceneFindItemBspTreeVisitor during the next repaint.
TL;DR: The solution is to ensure that QGraphicsItem::prepareGeometryChange() gets called before the item's removal from the scene.
The problem is that during the item removal from the scene, the scene internal index was not properly updated, resulting in the crash upon the next attempt of drawing the scene.
Since in my case, I use a custom subclass from QGraphicsPathItem, I simply put the call to QGraphicsItem::prepareGeometryChange() into its destructor since I am not manually removing the item from the scene (via QGraphicsScene::removeItem()), but instead I simply call delete pItem; which in return triggers the item's destructor as well as removeItem() later on.
I ran into the same issue using PySide2.
Disabling BSP indexing (as mentioned here) does work for me and is most likely the actual solution to the problem. But is a sub-optimal one, because the scene that I am working with can get arbitrarily large. I also tried to call prepareGeometryChange before removing the item, and while that did seem to work for a while, the error re-appeared just a few weeks later.
What worked for me (so far) is manually removing all child items before removing the item itself...
To that end, I am overwriting the QGraphicsScene::removeItem method in Python:
class GraphicsScene(QtWidgets.QGraphicsScene):
def removeItem(self, item: QtWidgets.QGraphicsItem) -> None:
for child_item in item.childItems():
super().removeItem(child_item)
super().removeItem(item)
Note that this will not quite work the same in C++ because QGraphicsScene::removeItem is not a virtual method, so you will probably have to add your own method removeItemSafely or whatever.
Disclaimer: Other methods have worked for me as well ... until they didn't. I have not seen a crash in QGraphicsSceneFindItemBspTreeVisitor::visit since introducing this workaround, but that does not mean that this is actually the solution. Use at your own risk.
I had this issue and it was a real pain to fix it. Besides the crash, I was also having "guost" items appearing on the screen.
I was changing the boundingRect size 2x inside a custom updateGeometry() method that updates the boundingbox and shape caches of the item.
I was initializing the boundig rectangle as QRectf():
boundingBox = QRectF();
... then doing some processing (and taking the opportunity to do some clean ups in unneeded objects from the scene).
And finally setting the value of the boundingRect to its new size:
boundingBox = polygon.boundingRect();
Calling prepareGeometryChange() in the beggining, alone, didn't solve the issue since I was changing it's size twice.
The solution was to remove the first attribution.
It seems the issue lasting for long time today and there are open bugs also.
But it seems to have a workaround, which I could find it useful and after hours of debugging and reading and investigations I have found it here:
https://forum.qt.io/topic/71316/qgraphicsscenefinditembsptreevisitor-visit-crashes-due-to-an-obsolete-paintevent-after-qgraphicsscene-removeitem/17
Some other tips and tricks regarding Graphics Scene here:
https://tech-artists.org/t/qt-properly-removing-qgraphicitems/3063/6

Cocos2d-x CCSprite Memory Usage ( releasing CCSprite)

I'm developing a game in cocos2dx v2.2.3. I did a test and I found some problem as below:
Problem: (In windows) When I run my game and checking TaskManager, I found my game took ~20MB memory (in average).
But After Adding these lines of code in Init() of my game Layer and Then it increases the memory usage up to 300MB.
CCSprite *t;
t = CCSprite::create("Character/foo1.png"); //Each picture is about 50MB
t->release();
t = CCSprite::create("Character/foo2.png");
t->release();
t = CCSprite::create("Character/foo3.png");
t->release();
t = CCSprite::create("Character/foo4.png");
t->release();
( I myself create these picture huge for this test)
I also checked m_uReference when t->release(); is calling. and there m_uReference is becoming 0 and so It should be deleted! But why memory use is that high?
Question: I wonder How should I delete/remove/release a CCSprite after some time?
Additional Info/Test:
I found something that may help. After calling t->release(); It somewhere reach :
CCSprite::~CCSprite(void) {
CC_SAFE_RELEASE(m_pobTexture);
}
But in CC_SAFE_RELEASE(m_pobTexture);, m_uReference of texture decrease from 2 to 1 and therefor the texture don't get deleted.
I did a test and make this change :
CCSprite::~CCSprite(void) {
CC_SAFE_RELEASE(m_pobTexture);
CC_SAFE_RELEASE(m_pobTexture);
}
And RAM returned to ~20MB. ( Also I know This's not the correct way and I missing something else)
First, your code is likely to crash somewhere down the line (unless you left out some code): CCSprite::create returns an autoreleased CCSprite, which means you don't need to .release() it (and if you don't .retain() it, it's going to be deleted shortly after).
For your question: CCSprite needs a CCTexture to works (your image is loaded in memory). But CCSprite don't own the CCTexture; the CCTexture is managed by CCTextureCache.
CCTextureCache don't release a CCTexture directly when no CCSprite use it anymore: instead, it keeps the CCTexture for future usage (since loading a CCTexture is expensive) and only release CCTexture when there is not enough memory or you force it to do so, with
CCTextureCache::sharedTextureCache()->removeUnusedTextures();
The short answer is: you shouldn't worry about memory used unless you have a real memory problem (game crashing because of lack of memory). Games are supposed to use a lot of memory.

Windows Forms - picture box. How to delete an Image

I am working in an application where there is a conbobox and a picturebox. The user selects a path and the conbobox loads paths to 2000 images, and displays the first one. When the user changes the index of the conbobox the image displayed changes, but I don't know how to delete the image in the picturebox.
If I just overwrite the image it doesnt do the job, as when I do it repeatedly the program crashes because of memory. How do I delete a image Inside the picturebox?
EDIT:
I made few changes and can't seem to reproduce the error again.. so maybe it was something else. but just for checking, is this code leaking memory?
tips: config is a singleton containing where some info, in this case, where the images are.
private: System::Void comboBox_image1_SelectedIndexChanged(System::Object^ sender, System::EventArgs^ e) {
System::String^ aux;
DIC_config* config=DIC_config::Instance();
if(config->images_path!=NULL){
aux=gcnew System::String(config->images_path);
aux=aux+"\\CAM_0\\Snap_0_0"+(this->comboBox_image1->SelectedIndex+1)+".bmp";
System::IO::FileStream^ image_file=gcnew System::IO::FileStream(aux,System::IO::FileMode::Open,System::IO::FileAccess::Read);
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(image_file);
this->pictureBox_image1->Image=img;
//img->~Bitmap(); this doesnt work, deletes the image of picturebox and makes the program chrash
}
}
You have to dispose the old image. Forgetting to do so makes it likely your program runs out of unmanaged memory when the garbage collector doesn't run frequently enough. Bitmap objects are quite small, you can allocate thousands of them without ever triggering a GC, but can consume a lot of unmanaged memory for the pixel data. You dispose objects in C++/CLI with the delete operator, it calls IDisposable::Dispose().
Do note that the FileStream you use is also a disposable object. Doing it this way requires you to keep the stream opened while the bitmap is in use and close it afterwards. You correctly did not dispose the stream but forgot closing it. Too hard to get right, it is much easier to use the Bitmap constructor that accepts a string for the file path so the Bitmap class manages the underlying stream itself. Fix:
aux = config->images_path;
aux += ....;
System::Drawing::Bitmap^ img = gcnew System::Drawing::Bitmap(aux);
delete this->pictureBox_image1->Image;
this->pictureBox_image1->Image = img;
This doesn't work because you are trying to call destructor of the class, not the instance. Furthermore you do not need to call it as System::Drawing::Bitmap is under control of garbage collector, so the finalizer ( !Bitmap() ) will be called automatically if it's not referenced any longer.
What you can do if you want to close it in picturebox is
delete this->pictureBox_image1->Image;
image_file->Close(); //after closing/deleting the open bitmap
btw. your code is not pure c++, but c++/cli, so I've added the tag
First set a null pointer to the Image property and refresh the pictureBox, as given below,
pictureBox_image1->Image = nullptr;
pictureBox_image1->Refresh();

C++: Cannot instantiate a pointer directly

This is an SDL problem, however I have the strong feeling that the problem I came across is not related to SDL, but more to C++ / pointers in general.
To make a long story short, this code doesn't work (edited to show what I really did):
player->picture = IMG_Load("player");
SDL_BlitSurface(player->picture, NULL, screen, &pictureLocation);
I see nothing on the screen. However, when I do it like this, it works:
SDL_Surface* picture = IMG_Load("player.png");
player->picture = picture;
SDL_BlitSurface(player->picture, NULL, screen, &pictureLocation);
I can see the little guy just fine.
The real problem is that I cannot instantiate Player::picture directly. Even when I try
picture = IMG_Load("player.png")
in player.cpp, I end up with a nullpointer.
I am so stupid. Turns out like I forgot the file extension ".png" every time I tried to store the surface in Player::picture, and conveniently remembered to add it every time I stired it in an SDL_Surface declared in main.cpp.
I had the feeling I was overlooking something really simple here, but this is just embarassing. What's a fitting punishment for this?
What data type is player->picture? What type does IMG_Load return? It's really hard to come up with a scenario where saving an expression in a temporary variable changes the result, unless a type conversion is involved.
And I wouldn't call this pointer instantiation. You're instantiating an instance of some picture type and storing a pointer to it.
This is why you should always check to see what IMG_Load() returns...
SDL_Surface* picture = IMG_Load("player.png");
if (picture == NULL) {
// there was obviously some sort of error.
// what does SDL_GetError() say?
}
Some SDL functions return -1 if there is an error. Just check the documentation and make sure you're checking your function returns. These steps make debugging a lot easier.