SFML community forums

Help => Window => Topic started by: awr on November 14, 2013, 03:05:38 pm

Title: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 14, 2013, 03:05:38 pm
I'm using SFML in a scenario where I need to spawn multiple windows (never simultaneously). SFML is being used inside a video player control inside a wider application and whenever a user goes to play a video, a new SFML window is created.

However, this seems to create a memory leak and I suspect it might be related to opengl contexts being created. I've attached both a C# and C++ version to demonstrate the issue.

private RenderWindow SFMLWindow = null;
private void RenderLoop()
        {
            //SFMLWindow = new RenderWindow(new VideoMode(400, 300), "SFML doesn't work(s)");    
 
            while(true)
            {
                SFMLWindow = new RenderWindow(new VideoMode(800, 600), "hello");
                SFML.Graphics.Texture texture = new Texture(1920, 1080);
                SFML.Graphics.Sprite sprite = new Sprite(texture);
                SFMLWindow.Draw(sprite);
                SFMLWindow.Display();
                SFMLWindow.Clear();

                System.Threading.Thread.Sleep(1000);

                SFMLWindow.Close();
                SFMLWindow.Dispose();

                System.Threading.Thread.Sleep(1000);

                texture.Dispose();
                sprite.Dispose();
            }
     }
 


int _tmain(int argc, _TCHAR* argv[])
{
        sf::RenderWindow window;

        while (true)
        {
                window.create(sf::VideoMode(800, 600), "leak");
                sf::Texture texture;           
                texture.create(1920, 1080);
                sf::Sprite sprite(texture);
                window.draw(sprite);
                window.display();
               
                Sleep(1000);

                window.clear();
                window.close();

                Sleep(1000);
        }
}
 
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: Laurent on November 14, 2013, 03:07:15 pm
What's the difference between this C++ code, and the previous one that didn't leak?
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 14, 2013, 03:12:21 pm
There is no difference. It's just that I had multiple instances of Visual Studio open and I was looking at the wrong task name.  :-[ Upon running the test again as a sanity check I noticed that it in fact was also leaking.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: eXpl0it3r on November 14, 2013, 03:18:36 pm
Too bad now my post on the deleted topic is gone. :-\

You should run an actual memory leak detection tool instead of guess from far with various tools. I highly doubt that you get leaks up to 7 MB for a 10 MB texture, it probably rather looks like "leaked".

I guess it's yet another context creation thingy, but can't be sure. That the garbage collector can't clean everything sounds reasonable given that SFML is not managed.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 14, 2013, 03:39:08 pm
Too bad now my post on the deleted topic is gone. :-\

You should run an actual memory leak detection tool instead of guess from far with various tools. I highly doubt that you get leaks up to 7 MB for a 10 MB texture, it probably rather looks like "leaked".

I guess it's yet another context creation thingy, but can't be sure. That the garbage collector can't clean everything sounds reasonable given that SFML is not managed.

To add to this, it's not the process of creating the texture that's leaking, I only see a leak when deleting the current window and instantiating a new one. I did run debugdiag and I do recall seeing leaks in ig7cd32.dll though at that point there was another (context related) leak in my code that I've since removed and isn't an issue in these minimal examples. I'll re-run debugdiag or some other unmanaged leak tool tomorrow to see if I can nail where the leak is coming from.

Also, from memory when I just create the texture and sprite but don't call window.draw(...), the leak didn't occur.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 15, 2013, 01:01:07 am
Strangely enough, running memory profile tools haven't detected a memory leak, but memory is definitely increasing and not dropping.

I ran the C++ test, with both sleep statements at 500ms, for 2 minutes.

Initially, memory (working set) was at 136MB. After 2 minutes, it had increased to 593MB. The texture size was 1200x600, or 2.74MB per second. The memory was increasing at a rate of 3.8MB per second.

Running the exact same test, except with the window.draw(sprite) line commented out, resulted in working set staying constant at about 42MB.

Hopefully the following code sample will hint at the issue:

int _tmain(int argc, _TCHAR* argv[])
{
        sf::RenderWindow window;

        while (true)
        {
                window.create(sf::VideoMode(600, 300), "SFML works! ");
                sf::Texture texture;           
                texture.create(1200, 600);
                sf::Sprite sprite(texture);
                window.draw(sprite);
                window.display();

                Sleep(500);

                sf::Texture smallTexture;
                smallTexture.create(1,1);
                sf::Sprite smallSprite(smallTexture);  

                window.clear();
                window.draw(smallSprite);
                window.display();
                window.close();

                Sleep(500);
        }
}

This code produces no noticeable leak, given that the texture is so small.

However, what seems to be happening is that the memory allocated to the last texture drawn to the window is not being released for whatever reason. This hack would work for my purposes as nobody's going to notice such a small leak but it's an ugly hack regardless.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: Laurent on November 15, 2013, 07:48:18 am
Sometimes it's the OpenGL driver that causes such a memory grow.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: eXpl0it3r on November 15, 2013, 08:18:13 am
With that being said, is your graphics driver up to date?
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: wintertime on November 15, 2013, 10:50:48 am
There are many different values of memory use in Windows and you are using the wrong one. The current working set is not the same as allocated memory.
Windows only gives an application a dynamically changing allowance of pages, that depends on recently used memory pages, and removes the rest from the working set to put them into some global cache, where they are technically still in memory, but are premarked to be swapped out if memory is needed later and may produce a page fault already which swaps a page back into the working set.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 16, 2013, 03:45:12 am
With that being said, is your graphics driver up to date?
I upgraded a month or so ago so its quite a recent problem. I haven't tested it on another machine but I don't think it's the driver.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 16, 2013, 03:48:48 am
There are many different values of memory use in Windows and you are using the wrong one. The current working set is not the same as allocated memory.
Windows only gives an application a dynamically changing allowance of pages, that depends on recently used memory pages, and removes the rest from the working set to put them into some global cache, where they are technically still in memory, but are premarked to be swapped out if memory is needed later and may produce a page fault already which swaps a page back into the working set.
From memory, private bytes was increasing at the same rate as working set.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: binary1248 on November 16, 2013, 10:51:21 am
binary1248 looks for other applications that rely on opening and closing windows (creating and destroying DCs often) to provide functionality...
binary1248 finds nothing...
binary1248 considers running to the wgl/driver support people to ask if this is normal...
wgl/driver support people ignore help request upon reading problem description...
binary1248 assumes there is no demand for support of such a use case, thereby obviating effort to fix it...

This is an operating system/driver issue. I'm sure merely creating a single device context already leaks some unnoticeable amount of memory, it's just that it is so little, and it is typically a one time operation that it isn't even considered as a leak (we know how people tend to bend definitions in their favour). As long as there isn't a AAA developer behind some complaint you can keep hoping that this will get fixed one day. Or you could just resort to typical use scenarios and avoid pushing the driver beyond what any "sane" developer would even consider doing.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 16, 2013, 11:58:07 am
binary1248 looks for other applications that rely on opening and closing windows (creating and destroying DCs often) to provide functionality...
binary1248 finds nothing...
binary1248 considers running to the wgl/driver support people to ask if this is normal...
wgl/driver support people ignore help request upon reading problem description...
binary1248 assumes there is no demand for support of such a use case, thereby obviating effort to fix it...

This is an operating system/driver issue. I'm sure merely creating a single device context already leaks some unnoticeable amount of memory, it's just that it is so little, and it is typically a one time operation that it isn't even considered as a leak (we know how people tend to bend definitions in their favour). As long as there isn't a AAA developer behind some complaint you can keep hoping that this will get fixed one day. Or you could just resort to typical use scenarios and avoid pushing the driver beyond what any "sane" developer would even consider doing.
Such presumptuous smugness us at best unhelpful and at worst detrimental. Your inability to think up a scenario where multiple windows are created isn't indicative of an insane scenario.

FYI, I'm not creating windows for the fun of it. SFML is being used inside a windows forms control with the window actually a picturebox in the form (instantiated by passing the handle). The form is a video player control, with SFML responsible for the video rendering. Its used inside a wider application where users can view videos, in which case the an instance of the video player is created and a new window alongside it. The video playback is a periphery feature and thus the control is disposed after playback. The control can also be used an activex component in IE and on each refresh an instance is created.

Pray tell, with your no doubt boundless understanding of programming and programming techniques, how the above constitutes an insane use case, or even a particularly unorthodox one? With your use of useless rhetoric like AAA developer you are no doubt a bastion of knowledge.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: eXpl0it3r on November 16, 2013, 12:47:30 pm
I upgraded a month or so ago so its quite a recent problem. I haven't tested it on another machine but I don't think it's the driver.
You're not helping yourself or anyone else by assuming such a thing. ;)
Even if drivers are marked as "stable" they can contain bugs and what binary1248 tried to point out is, that no matter what you or even a group of us people do, the driver maintainers won't fix the bug for us. They really don't care unless you're a big company, sad but true.

I've run your code for a few minutes and it probably created around 100 or more windows and my memory consumption never went over 20 MiB. It often went up to 18 MiB but then the OS kicked in and detatched the unused memory and it went down to 11-13 MiB.
So I'm not sure what you're looking for. If the memory leak detector doesn't detect anything, if it doesn't visually leak on all systems and if the leak (if at all) is only a few bytes. Sure it's bad if there's a leak, but is it worth all the time you've already spent and we've already spent trying to hunt down something that wouldn't be an issue in about any scenario. What if the application uses a few MiB more? To make it an issue would be to create thousands of new windows, if that's the case, then you'd might want to think about a virtual windowing system anyways. ;)
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: binary1248 on November 16, 2013, 12:48:49 pm
I wonder who is the one who misunderstands the other... You obviously assume that I don't understand what you are trying to do. It is kind of obvious since you stated it multiple times in your previous posts. The difference between you using SFML to create a video player control and "other" such applications is that in the latter case, the control doesn't constantly go though context/window creation and destruction that often because it is designed to be used as a control within an owning Window. The fact that SFML allows you to do this does not imply that that is what it was designed for. You can loathe this fact as much as you want but that will not change anything. If the reverse was true, SFML context management would look entirely different, but then it wouldn't be able to be used standalone, and I think we know which use case occurs more...

And about "sane" usage. If you really think I were so atrocious as to define what "sane" usage was, then you haven't dealt with this kind of issue enough. It has occurred time and again that "something" is not well if at all supported. If you dig deeper you will not find any useful information, and it might sound like a conspiracy theory, but I think anyone with common sense will understand why certain groups are not willing to invest time/money into certain things and a ludicrous amount in others. I'm not the one you should ask what "sane" is. Maybe the better term would be "typical", however being "atypical" would also be seen as degrading by some. So please do suggest a term that properly describes a minority group that does something differing in a large way from the main group because they are not aware of or don't want to embrace the fact that the main group is the group with more support. I find "sane" very descriptive in this case.

And since we are already in that area, open up the release notes of the last driver version provided for your graphics hardware, read a few of the points listed in the list related to the latest gaming titles you can currently procure. Find a phrase  that unambiguously describes the people who develop those titles and prevents confusion with any other form of developer who doesn't make it onto that list. The only thing I could come up with is "AAA developer", your turn, suggest something. If I were in the mood I could also label it as useless rhetoric, but to be honest, I have better things to do than play these games.

Just to be clear, I am not against anything you are doing. I am just stating the current situation. You can like or dislike it, but that doesn't change much. I've browsed through SFML's context code multiple times trying to isolate what could cause this problem because I do take an interest in making SFML better, this also means I suggest improvements to the SFML codebase and rarely provide workarounds for certain projects because this detracts from the overall effort to improve SFML instead of the applications that use it. I can only assume you haven't gone so far, otherwise you would have mentioned it already. I don't really care if you take my efforts for granted, however that is still no reason to lash back because it is not what you would have expected as an outcome. I am not someone who comforts those in need. I provide them with cold hard facts whether they like it or not. There are enough people who hide reality in order to achieve something, but that is not my idea of progress.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 16, 2013, 01:07:22 pm
Semantics aside (I'll take your post at face value that you didn't imply my usage scenario was insane), I tried it on my home machine and I couldn't reproduce the memory leak, so it does seem to be a graphics driver issue.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: binary1248 on November 16, 2013, 01:44:59 pm
Code: [Select]
//                                                                         
// Each log entry has the following syntax:                                 
//                                                                         
// + BYTES_DELTA (NEW_BYTES - OLD_BYTES) NEW_COUNT allocs BackTrace TRACEID
// + COUNT_DELTA (NEW_COUNT - OLD_COUNT) BackTrace TRACEID allocations     
//     ... stack trace ...                                                 
//                                                                         
// where:                                                                   
//                                                                         
//     BYTES_DELTA - increase in bytes between before and after log         
//     NEW_BYTES - bytes in after log                                       
//     OLD_BYTES - bytes in before log                                     
//     COUNT_DELTA - increase in allocations between before and after log   
//     NEW_COUNT - number of allocations in after log                       
//     OLD_COUNT - number of allocations in before log                     
//     TRACEID - decimal index of the stack trace in the trace database     
//         (can be used to search for allocation instances in the original 
//         UMDH logs).                                                     
//                                                                         


+  ff3806 ( ff3806 -     0)    7fa allocs BackTrace21C5
+     7fa (   7fa -     0) BackTrace21C5 allocations

ntdll!RtlLogStackBackTrace+00000007
ntdll!RtlImageNtHeader+00000B6A
atioglxx!DrvPresentBuffers+00F19ED9
atioglxx!DrvPresentBuffers+0014626E
atioglxx!DrvPresentBuffers+0014636C
atioglxx!DrvPresentBuffers+001452F3
atioglxx!DrvPresentBuffers+002088EE
atioglxx!DrvPresentBuffers+001B8A36
atioglxx!DrvPresentBuffers+00147608
atioglxx!DrvPresentBuffers+00354653
atioglxx!DrvPresentBuffers+00170B8C
Test!???+00000000 : 404D22
Test!???+00000000 : 4017AE
Test!???+00000000 : 4045CB
Test!???+00000000 : 445CDC
Test!???+00000000 : 4013DB
kernel32!BaseThreadInitThunk+00000012
ntdll!RtlInitializeExceptionChain+00000063
ntdll!RtlInitializeExceptionChain+00000036
Alias
ntdll!RtlLogStackBackTrace+00000007
ntdll!RtlImageNtHeader+00000B6A
atioglxx!DrvPresentBuffers+00F19ED9
atioglxx!DrvPresentBuffers+00185EFA
atioglxx!DrvPresentBuffers+000DD74A
atioglxx!DrvPresentBuffers+0009D8F6
atioglxx!DrvPresentBuffers+00921C53
atioglxx!DrvPresentBuffers+00920A79
atioglxx!DrvPresentBuffers+00925EDB
atioglxx!DrvCreateLayerContext+00000113
OPENGL32!wglSwapMultipleBuffers+00001420
OPENGL32!wglCreateLayerContext+00000098
OPENGL32!wglCreateContext+0000000F
Test!???+00000000 : 41B02A
Test!???+00000000 : 41B987
Test!???+00000000 : 41957C
Test!???+00000000 : 418512
Test!???+00000000 : 445E3C
Test!???+00000000 : 4013DB
kernel32!BaseThreadInitThunk+00000012
ntdll!RtlInitializeExceptionChain+00000063
ntdll!RtlInitializeExceptionChain+00000036

+  fe380e ( fe380e -     0)    7f2 allocs BackTraceB546
+     7f2 (   7f2 -     0) BackTraceB546 allocations

ntdll!RtlLogStackBackTrace+00000007
ntdll!RtlImageNtHeader+00000B6A
atioglxx!DrvPresentBuffers+00F19ED9
atioglxx!DrvPresentBuffers+0014626E
atioglxx!DrvPresentBuffers+0014636C
atioglxx!DrvPresentBuffers+001452F3
atioglxx!DrvPresentBuffers+002088EE
atioglxx!DrvPresentBuffers+001B8A36
atioglxx!DrvPresentBuffers+00147608
atioglxx!DrvPresentBuffers+00354653
atioglxx!DrvPresentBuffers+00170B8C
Test!???+00000000 : 404D22
Test!???+00000000 : 4017AE
Test!???+00000000 : 4045CB
Test!???+00000000 : 445CDC
Test!???+00000000 : 4013DB
kernel32!BaseThreadInitThunk+00000012
ntdll!RtlInitializeExceptionChain+00000063
ntdll!RtlInitializeExceptionChain+00000036

+  fb1827 ( fb1827 -     0)    7d9 allocs BackTraceEB82
+     7d9 (   7d9 -     0) BackTraceEB82 allocations

ntdll!RtlLogStackBackTrace+00000007
ntdll!RtlImageNtHeader+00000B6A
atioglxx!DrvPresentBuffers+00F19ED9
atioglxx!DrvPresentBuffers+0014626E
atioglxx!DrvPresentBuffers+0014636C
atioglxx!DrvPresentBuffers+001452F3
atioglxx!DrvPresentBuffers+002088EE
atioglxx!DrvPresentBuffers+001B8A36
atioglxx!DrvPresentBuffers+00147608
atioglxx!DrvPresentBuffers+00354653
atioglxx!DrvPresentBuffers+00170B8C
Test!???+00000000 : 404D22
Test!???+00000000 : 4017AE
Test!???+00000000 : 4045CB
Test!???+00000000 : 445CDC
Test!???+00000000 : 4013DB
kernel32!BaseThreadInitThunk+00000012
ntdll!RtlInitializeExceptionChain+00000063
ntdll!RtlInitializeExceptionChain+00000036
This is the beginning of the output of a UMDH compare between 2 log files generated a few minutes a part. As can be seen, all the allocations take place somewhere in the AMD driver which is in turn called by WGL and are not deallocated somewhere in the AMD driver when the corresponding WGL commands are issued to free resources. The rest of the file looks pretty much the same another 40000 lines. AMD/ATI is known for caring a lot about a clean driver and Microsoft is known for their OpenGL support, so this isn't something I would lose sleep over.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: binary1248 on November 16, 2013, 03:54:45 pm
To put the final nail in the coffin, even this minimal code sample will cause memory usage to constantly rise:
#include <windows.h>
#include <GL/gl.h>

int main() {
        auto window = CreateWindowA( "STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle( NULL ), NULL );
        ShowWindow( window, SW_HIDE );
        auto deviceContext = GetDC( window );

        PIXELFORMATDESCRIPTOR descriptor;
        ZeroMemory( &descriptor, sizeof( descriptor ) );
        descriptor.nSize        = sizeof( descriptor );
        descriptor.nVersion     = 1;
        descriptor.iLayerType   = PFD_MAIN_PLANE;
        descriptor.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
        descriptor.iPixelType   = PFD_TYPE_RGBA;
        descriptor.cColorBits   = 32;
        descriptor.cDepthBits   = 24;
        descriptor.cStencilBits = 8;
        descriptor.cAlphaBits   = 0;

        auto format = ChoosePixelFormat( deviceContext, &descriptor );
        SetPixelFormat( deviceContext, format, &descriptor );

        while( true ) {
                auto context = wglCreateContext( deviceContext );

                wglDeleteContext( context );
        }

        ReleaseDC( window, deviceContext );
        DestroyWindow( window );
}
Since the loop only makes calls to wgl, it is wgl or the driver that is causing the leak for sure.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: awr on November 17, 2013, 03:22:23 am
To put the final nail in the coffin, even this minimal code sample will cause memory usage to constantly rise:
#include <windows.h>
#include <GL/gl.h>

int main() {
        auto window = CreateWindowA( "STATIC", "", WS_POPUP | WS_DISABLED, 0, 0, 1, 1, NULL, NULL, GetModuleHandle( NULL ), NULL );
        ShowWindow( window, SW_HIDE );
        auto deviceContext = GetDC( window );

        PIXELFORMATDESCRIPTOR descriptor;
        ZeroMemory( &descriptor, sizeof( descriptor ) );
        descriptor.nSize        = sizeof( descriptor );
        descriptor.nVersion     = 1;
        descriptor.iLayerType   = PFD_MAIN_PLANE;
        descriptor.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
        descriptor.iPixelType   = PFD_TYPE_RGBA;
        descriptor.cColorBits   = 32;
        descriptor.cDepthBits   = 24;
        descriptor.cStencilBits = 8;
        descriptor.cAlphaBits   = 0;

        auto format = ChoosePixelFormat( deviceContext, &descriptor );
        SetPixelFormat( deviceContext, format, &descriptor );

        while( true ) {
                auto context = wglCreateContext( deviceContext );

                wglDeleteContext( context );
        }

        ReleaseDC( window, deviceContext );
        DestroyWindow( window );
}
Since the loop only makes calls to wgl, it is wgl or the driver that is causing the leak for sure.

I tried this code sample on my home machine and like the previous, it didn't leak. Very concerning that it is a driver issue - almost certainly means that I'll have to use a different approach. Thanks for your help in shedding light on the culprit.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: Jeanne-Kamikaze on June 18, 2014, 04:22:42 pm
Has the memory leak issue been fixed as of 2.1? Texture loading on my side fails with an "out of memory" error when I create a window, load a texture, destroy the window and loop this process multiple times. I will now try to make a minimal example to reproduce this error.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: binary1248 on June 18, 2014, 04:35:14 pm
There are 2 issues on the table here. On the one hand, due to the way SFML manages contexts in multiple threads, leaks can occur when directly or indirectly creating contexts in secondary threads. This only occurs in multi-threaded scenarios, so probably not that often. On the other hand, the code I already posted demonstrates that the driver itself leaks, so unless SFML implements some sort of hackish workaround (I have no idea how and if this is possible), there is no way around this other than to go to the forums of the driver developers and convince them that you are more important than many of their other clientèle and hope they fix the issue on their end.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: Jeanne-Kamikaze on June 19, 2014, 02:44:04 pm
It seems I missed the part of the post where you state that that snippet does actually leak. It's so insultingly minimal, I can't believe modern drivers suck so hard that even that goes wrong. If I am not mistaken, this wgl thing is Microsoft stuff, isn't it? Perhaps it's yet another scheme to shun people away from OpenGL and over to DirectX.
Title: Re: Significant memory leak in SFML when creating multiple windows
Post by: Jesper Juhl on June 20, 2014, 08:23:11 pm
Or maybe it's a reason to use Open Source drivers (although those also suck, but at least the code is available) ;)
Most code sucks. Commercial, closed-source code sucks especially hard - I've honestly not worked for a company yet where there were not *huge* dragons and WTF's in the code. So seriously, what did you expect?
It all sucks, you just have to try and find the bits that suck a little less compared to the rest.

Edit: yeah, I know. I'm a grumpy old man by now.