How to de-allocate memory of a QT-OCC view?

Hello!
I am working with Qt 4.7.3 and OCC 6.5.3.
I have a problem with memory-management or maybe I just misunderstand OCC-Handles?

My application needs to create and destroy OCC windows many times, we are able to float and split the windows everything seems to work fine except that we are not able to release even 1KB of the views memory...
Here is some code from a simplifyed testView ... it's based on the Qt_occ examples.

TestViewOCC::TestViewOCC(QWidget * parent, LDSDoc * document)
: QWidget(parent), LDSView(document), currentAction(CA_NOTHING) , rotCenter(0.0, 0.0, 0.0), degenerateMode(true), firstPaint(true)
, occDefaultDevice(nullptr), occViewer(nullptr), occView(nullptr), occContext(nullptr),localContextIndex(-1),occOvlLayer(nullptr), hWnd(nullptr), s_factor(0.0), tw_factor(0.0)//, mouseLast(NULL), rotScrCent(NULL)
,backgroundColor(Quantity_Color(.200, .200, .400, Quantity_TOC_RGB)), mouseLast(0.0,0.0), rotScrCent(0.0,0.0), eyex(0.0), eyey(0.0), eyez(0.0), viewx(0.0), viewy(0.0), viewz(0.0),
makeHitTest(false),doubleClickFlag(false),mouseClickFlag(false)
{
setAttribute(Qt::WA_DeleteOnClose);
setFirstPaint(true);

occDefaultDevice=new Graphic3d_WNTGraphicDevice();
TCollection_ExtendedString viewName("LDSGeom3DView");
occViewer=new V3d_Viewer(occDefaultDevice, viewName.ToExtString(), (Standard_CString)"", 1000., V3d_XposYnegZpos,
backgroundColor.Name(),V3d_ZBUFFER,V3d_GOURAUD,V3d_WAIT, Standard_True, Standard_True, V3d_TEX_NONE);
occViewer->Init();
//occViewer->SetZBufferManagment( Standard_False );
occViewer->SetDefaultBackgroundColor(backgroundColor);

occViewer->SetLightOff(); // NOTE tbam: we have to turn all lights off because we don't want the default lightsource!

occContext=new AIS_InteractiveContext(occViewer);
occContext->SelectionColor(Quantity_NOC_ORANGE);
setAutoFillBackground(false);
setAttribute(Qt::WA_NoSystemBackground);
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_WState_Visible, false);
setMouseTracking(true);
setBackgroundRole(QPalette::NoRole);
setFocusPolicy(Qt::StrongFocus);

if(occView.IsNull())
{
occView = occViewer->CreateView();
}

if(degenerateMode)
{
//occView->SetComputedMode(true);
occView->SetDegenerateModeOn();
}
else
{
//occView->SetComputedMode(false);
occView->SetDegenerateModeOff();
}
occView->TriedronDisplay(Aspect_TOTP_RIGHT_LOWER,Quantity_NOC_GREEN,0.08,V3d_WIREFRAME);
occView->MustBeResized();
occView->SetTransparency(true);
}

...
and the paint method
...

void TestViewOCC::paintEvent(QPaintEvent * e)
{
if(isFirstPaint())
{
if(occView.IsNull())
{
occView = occViewer->CreateView();
}

if(hWnd.IsNull())
{
hWnd = new WNT_Window(Handle(Graphic3d_WNTGraphicDevice)::DownCast(occViewer->Device()), winId());
occView->SetWindow(hWnd);
}
else
{
hWnd->Map();
}

if(!hWnd->IsMapped())
hWnd->Map();

hWnd->SetDoubleBuffer(Standard_True);
hWnd->SetFlags(WDF_NOERASEBKGRND);

if(degenerateMode)
{
occView->SetDegenerateModeOn(); //obsolete
}
else
{
occView->SetDegenerateModeOff(); //obsolete
}
occView->TriedronDisplay(Aspect_TOTP_RIGHT_LOWER,Quantity_NOC_GREEN,0.08,V3d_WIREFRAME);
occView->MustBeResized();
occView->SetTransparency(true);
//occView->SetVisualization(V3d_WIREFRAME);
occOvlLayer=new Visual3d_Layer(occViewer->Viewer(), Aspect_TOL_OVERLAY, Standard_False);
s_factor = occView->Scale();
setFirstPaint(false);
}
occView->Redraw();
}

...as you can see, we're working with OCC handles all the time (maybe we shouldn't do that?).
The problem now is that (even if I try to nullify all of these handles in the view) no memory seems to be released when the view is closed.

TestViewOCC::~TestViewOCC()
{
// I just tried sth....

occContext->CloseAllContexts();
occContext->RemoveAll();
occContext.Nullify();
hWnd->Unmap();
hWnd.Nullify();
occView.Nullify();
occViewer.Nullify();
occOvlLayer.Nullify();
occDefaultDevice.Nullify();

... and much more

//no changes at all, nothing changes even if we reduce the view to the minimum (no context, no Visual3d_Layer..., only a V3d_Viewer, a V3d_View and the hWnd)
}

When I try to debug, f.e. the destructor of WNT_Window is called (even if I don't nullify) , but the DestroyWindow()-function is NEVER called, why?

void WNT_Window :: Destroy ()
{
...
if ( !( myExtraData.dwFlags & WDF_FOREIGN ) ) /// dwFlags is always 3 ->
DestroyWindow ( ( HWND )myHWindow ); /// IS NEVER REACHED !
...
}

Note that the hWnd handles refCount is up to 3 already after calling the constructor (hWnd = new WNT_Window(Handle(Graphic3d_WNTGraphicDevice)::DownCast(occViewer->Device()), winId());)
But I guess that this is usual.

What am I doing wrong? Any hints?

I wondering the qt-occ example does work exactly the same way...
So with these example views it seems that we are not able to release any of a occ-views resources until we close the application. Why?
Does someone have experience with Qt-OCC views and how to release the memory correct?

Thanks, max

max pr's picture

I solved some of our memory issues by following Lygin's hint, to use const Handle(AIS_...)& instead of plain Handle(AIS_...)
whenever possible.

http://opencascade.blogspot.co.at/2008/11/open-cascade-handles-lets-hand...

I changed the handle usage only for our AIS_InteractiveObject - dervied classes so far, and their resources now get freed and returned to the system when a view (with displayed objects) is closed...

The views resources itself are still not freed, but memory consumption increases in a passable range now.
The first opened Qt-OCC view takes about 26 MB and each additional view about 5 MB.
I tried to set the window flags of the WNT_Windows myExtraData.dwFlags and got the DestroyWindow (...) function called, but this did not lead to a benefit(Furthermore the bigger part of the memory is reserved during V3d_View->setWindow()...).

The best results I received with MMGT_OPT 1, MMGT_CLEAR 1 and MMGT_REENTRANT 0, using TBB (MMGT_OPT 1 and MMGT_REENTRANT 1) lead us to a higher consumption, furthermore we don't use multithreading so far...
MMGT_THRESHOLD did not have big influence on the few tests I did, so for now we use default value here...

A problem still exists is the load/save mechanism. F.e. IGES-loading leads to a untendable memory leak. I tried to solve it again following Lygin blog:
http://opencascade.blogspot.co.at/2009/03/unnoticeable-memory-leaks-part...
But without success so far.

Maybe someone has a clean example-code of loading an IGES-file without leaks?
Anyway I will post the solution when solved...