Memory Leak in wxWidgets?

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
Scorcher24
Earned some good credits
Earned some good credits
Posts: 128
Joined: Sat Sep 25, 2004 9:11 pm
Location: Nuremberg, Germany
Contact:

Post by Scorcher24 »

Hi Folks !!

I have the originally the same problem.

The Problem is, that every time OnPaint(..) is called the memory usage increases about 8 - 12 bytes. In the Penguin sample it is every time you move the nice little animal, in my application it is every frame. ( Animation is done with a timer event).
I have wrote a complete Shader Designer, and I didn't recognize that problem at all first. After working 2 Hours with my ShaderDesigner I have recognized that my computer needs a long time to do simple ops like opening a folder. And the Taskmanager (again) said that my app is using 215MB Ram and rising. So I have tracked down everything. All pointers are dereferenced and deleted where applicable -> in the RenderFunc there are no pointers, and this is pretty small since it only renders a cube or a teapot or a sphere, all textured and displaylists.

I have found out that this problem is in wxWindows 2.4.2 AND in 2.5.5, the actual snapshot.

So, does anyone know, how to workaround ?? I have already searched the mailing list, but found nothing helpful.

rya.
Scorcher24
OS: Windows 7 Ultimate 64bit
IDE: VC++ 2008 Professional
WX: 2.9.2
My Projects
terranim
Experienced Solver
Experienced Solver
Posts: 56
Joined: Fri Jun 10, 2005 3:48 pm
Location: UK
Contact:

Post by terranim »

We have just converted our OpenIllusionist framework to wxWidgets. Overall I'm very impressed with it. But I have discovered this same problem with OpenGL rendering.

The leak seems to occur when the SetCurrent() and SwapBuffers() functions are called in the OnPaint of the wxGLCanvas derived class. It can be seen as a gradual rise in Task Manager of around 6Kb per second.

This is quite bad for us, since our software potentially has to be able to cope with running for long periods of time! Hoping someone has some suggestions since we don't want to have to start looking for another cross-platform development library at this stage

The problem occurs in both debug and release mode. The software was compiled and run using
WindowsXP
Visual Studio .NET
wxWidgets 2.6.1

Regards,
Dan
terranim
Experienced Solver
Experienced Solver
Posts: 56
Joined: Fri Jun 10, 2005 3:48 pm
Location: UK
Contact:

Post by terranim »

Update:

Out of curiosity I checked our software on my home computer. It behaved slightly differently, in that it didn't gradually increase it's memory usage while rendering!

There are some major differences between my system and the work one.
I am running Win2k whereas the work machine is running WinXP
My computer uses an nVidia graphics card whereas the work one uses an ATI
My computer has an Athlon processor whereas the other has a Pentium 4

I assume it has something to do with either the OS or possibly graphics card drivers and not actually a problem with wxGLCanvas (have looked at it's code and all it is doing when you call SwapBuffers is call the windows SwapBuffers function).

If people could try the demos (you must actually cause them to repaint with keys or mouse) and monitor the memory usage and report here whether or not you get the same problem described above and also what system you are using we may be able to pinpoint the reason.

Thanks,
Dan
terranim
Experienced Solver
Experienced Solver
Posts: 56
Joined: Fri Jun 10, 2005 3:48 pm
Location: UK
Contact:

Post by terranim »

Ok, nobody really seems to be posting here. But I have run some more tests, this time using a WinXP machine with an nVidia card and again there was no leak.

This leads me to believe that it is a problem linked with the ATi drivers, and I've tried updating to the latest with no luck!

I finally came to realise, after much playing with the code, that it is a problem with the call to wglMakeCurrent. nVidia systems don't seem to care if it is called multiple times, but ATi systems seem to gradually use memory each time it is called. The implementation in wxWidgets means that it is called each time SwapBuffers is called, and so is activated every frame. Since I only have one rendering context in my program there is no need to SetCurrent regularly. So, I have modified my overridden wxGLCanvas::OnPaint so that SetCurrent is only called once, and have also modified the wxGLContext::SwapBuffers function in the library so that it does not call wglMakeCurrent.

I am not sure if this should be submitted as a bug fix? Since people may already have code that relies on wglMakeCurrent being called in SwapBuffers? I have also never submitted a fix before. Could someone please advise me.

Thanks,
Dan
User avatar
Ryan Norton
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

terranim wrote:Ok, nobody really seems to be posting here. But I have run some more tests, this time using a WinXP machine with an nVidia card and again there was no leak.

This leads me to believe that it is a problem linked with the ATi drivers, and I've tried updating to the latest with no luck!

I finally came to realise, after much playing with the code, that it is a problem with the call to wglMakeCurrent. nVidia systems don't seem to care if it is called multiple times, but ATi systems seem to gradually use memory each time it is called. The implementation in wxWidgets means that it is called each time SwapBuffers is called, and so is activated every frame. Since I only have one rendering context in my program there is no need to SetCurrent regularly. So, I have modified my overridden wxGLCanvas::OnPaint so that SetCurrent is only called once, and have also modified the wxGLContext::SwapBuffers function in the library so that it does not call wglMakeCurrent.

I am not sure if this should be submitted as a bug fix? Since people may already have code that relies on wglMakeCurrent being called in SwapBuffers? I have also never submitted a fix before. Could someone please advise me.

Thanks,
Dan
There's arn't a lot of people who use WX that know much (if anything) about OpenGL... in fact there are probably more on this forum then even in the wx devs themselves.

As for this, why don't you post the patch or something similar in either here or in the code dump... at least I'll comment on it :).
[Mostly retired moderator, still check in to clean up some stuff]
terranim
Experienced Solver
Experienced Solver
Posts: 56
Joined: Fri Jun 10, 2005 3:48 pm
Location: UK
Contact:

Post by terranim »

Well the patch isn't much of a patch simply a commenting out of one line of code:

src/msw/glcanvas.cpp

Code: Select all

void wxGLContext::SwapBuffers()
{
  if (m_glContext)
  {
    //wglMakeCurrent((HDC) m_hDC, m_glContext);
    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
  }
}
But this does mean that the context has to be set (only once if you are using a single rendering context) before you call SwapBuffers (but then this is how you should code it using straight opengl anyway).

Regards,
Dan
User avatar
Ryan Norton
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

terranim wrote:Well the patch isn't much of a patch simply a commenting out of one line of code:

src/msw/glcanvas.cpp

Code: Select all

void wxGLContext::SwapBuffers()
{
  if (m_glContext)
  {
    //wglMakeCurrent((HDC) m_hDC, m_glContext);
    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
  }
}
But this does mean that the context has to be set (only once if you are using a single rendering context) before you call SwapBuffers (but then this is how you should code it using straight opengl anyway).

Regards,
Dan
Yes... maybe checking wglGetCurrentDC or whatnot before SwapBuffers and then calling wglMakeCurrent if the dc is not current would be appropriate?
[Mostly retired moderator, still check in to clean up some stuff]
terranim
Experienced Solver
Experienced Solver
Posts: 56
Joined: Fri Jun 10, 2005 3:48 pm
Location: UK
Contact:

Post by terranim »

Cheers,

This seems to work ok

Code: Select all

void wxGLContext::SwapBuffers()
{
  if (m_glContext)
  {
    if (wglGetCurrentContext() != m_glContext) wglMakeCurrent((HDC) m_hDC, m_glContext);
    //wglMakeCurrent((HDC) m_hDC, m_glContext);
    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
  }
}
Maybe the SetCurrent() function should also have that check in, just to avoid potential problems?

Dan
theWolf
Knows some wx things
Knows some wx things
Posts: 43
Joined: Wed May 18, 2005 12:27 am

Thank you

Post by theWolf »

Good job guys.
Sorry I found this thread late.
This will save me a big headache in the future.

I once spent about 40 hours on an OpenGL tech support problem that turned out to be a bad ATI driver on a customers (Winbook running XP).

Thank you.

:D
______________
WxWidgets 2.6.1, .net 2003, Windows2000
Sometimes there's a lot of gravel around the gems. WxWidgets is a gem!
User avatar
Ryan Norton
wxWorld Domination!
wxWorld Domination!
Posts: 1319
Joined: Mon Aug 30, 2004 6:01 pm

Post by Ryan Norton »

terranim wrote:Cheers,

This seems to work ok

Code: Select all

void wxGLContext::SwapBuffers()
{
  if (m_glContext)
  {
    if (wglGetCurrentContext() != m_glContext) wglMakeCurrent((HDC) m_hDC, m_glContext);
    //wglMakeCurrent((HDC) m_hDC, m_glContext);
    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
  }
}
Maybe the SetCurrent() function should also have that check in, just to avoid potential problems?

Dan
Sure, maybe do that and put SetCurrent in SwapBuffers instead of

Code: Select all

if (wglGetCurrentContext() != m_glContext) wglMakeCurrent((HDC) m_hDC, m_glContext);
See how that works maybe
[Mostly retired moderator, still check in to clean up some stuff]
sethjackson
Super wx Problem Solver
Super wx Problem Solver
Posts: 396
Joined: Wed Oct 05, 2005 1:19 am

Post by sethjackson »

This thread is a year old I know, but this problem is still in the wx code.
I have wx 2.6.3. Anyways bug report is here.

http://sourceforge.net/tracker/index.ph ... tid=109863
vdumont
I live to help wx-kind
I live to help wx-kind
Posts: 155
Joined: Wed Mar 29, 2006 7:13 pm
Location: QC,Canada

Post by vdumont »

Well putting a window on top of your wxGLCanvas and removing it, and so-on, causes the EVT_PAINT to be called each time, which re-draws everything. There is your memory usage increase, and it's quite normal.
theigor
Experienced Solver
Experienced Solver
Posts: 78
Joined: Thu Jan 12, 2006 6:51 pm

Post by theigor »

Well thanks to sethjackson, I guess, who ressurected the thread. I'll try changing my sources in that way and see what happens
sethjackson
Super wx Problem Solver
Super wx Problem Solver
Posts: 396
Joined: Wed Oct 05, 2005 1:19 am

Post by sethjackson »

vdumont wrote:Well putting a window on top of your wxGLCanvas and removing it, and so-on, causes the EVT_PAINT to be called each time, which re-draws everything. There is your memory usage increase, and it's quite normal.
See below.
theigor wrote:Well thanks to sethjackson, I guess, who ressurected the thread. I'll try changing my sources in that way and see what happens
That should stop the leak. Although the change proposed to the SwapBuffers() call would drastically reduce this (if not stop it completely). The real problem lies with ATI's OpenGL graphics driver.
This leak doesn't happen with nVidia cards, only with some ATI cards. For example I have a Mobility Radeon 9200 on a HP zx5000 laptop. This card does not leak (I have the drivers supplied by HP). My friend has a ATI Radeon X300 in a Dell D810. He uses the drivers from Dell. Every time my app calls SwapBuffers() (the real problem lies with wglMakeCurrent() inside that call) his memory usage increases by 500k - 1MB. :P On my system I do mot have this behavior.

See these gamdev.net postings for why it leaks. I would still like to see this "fixed" in the wx code (the code above should fix the problem).

http://www.gamedev.net/community/forums ... hichPage=1
http://www.gamedev.net/community/forums ... A%ED%BA%92
Vexator
I live to help wx-kind
I live to help wx-kind
Posts: 187
Joined: Sun Jan 30, 2005 2:50 pm
Location: Heidelberg, Germany

Post by Vexator »

(the code above should fix the problem)
which one? this one:

Code: Select all

void wxGLContext::SwapBuffers()
{
  if (m_glContext)
  {
    if (wglGetCurrentContext() != m_glContext) wglMakeCurrent((HDC) m_hDC, m_glContext);
    //wglMakeCurrent((HDC) m_hDC, m_glContext);
    ::SwapBuffers((HDC) m_hDC);    //blits the backbuffer into DC
  }
}
?!
Windows 7 Pro
Visual Studio 2010
wxWidgets 2.9.3
Post Reply