Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Significant memory leak in SFML when creating multiple windows  (Read 16302 times)

0 Members and 1 Guest are viewing this topic.

awr

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Significant memory leak in SFML when creating multiple windows
« Reply #15 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.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Significant memory leak in SFML when creating multiple windows
« Reply #16 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.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Significant memory leak in SFML when creating multiple windows
« Reply #17 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.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

awr

  • Newbie
  • *
  • Posts: 15
    • View Profile
Re: Significant memory leak in SFML when creating multiple windows
« Reply #18 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.

Jeanne-Kamikaze

  • Newbie
  • *
  • Posts: 20
    • View Profile
    • ShellBlade
Re: Significant memory leak in SFML when creating multiple windows
« Reply #19 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.

binary1248

  • SFML Team
  • Hero Member
  • *****
  • Posts: 1405
  • I am awesome.
    • View Profile
    • The server that really shouldn't be running
Re: Significant memory leak in SFML when creating multiple windows
« Reply #20 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.
SFGUI # SFNUL # GLS # Wyrm <- Why do I waste my time on such a useless project? Because I am awesome (first meaning).

Jeanne-Kamikaze

  • Newbie
  • *
  • Posts: 20
    • View Profile
    • ShellBlade
Re: Significant memory leak in SFML when creating multiple windows
« Reply #21 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.

Jesper Juhl

  • Hero Member
  • *****
  • Posts: 1405
    • View Profile
    • Email
Re: Significant memory leak in SFML when creating multiple windows
« Reply #22 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.
« Last Edit: June 20, 2014, 08:24:47 pm by Jesper Juhl »