PDA

View Full Version : Memory accumulation up to overflow by OpenGL-Ctrl



klickediklick
05-01-2010, 02:43 PM
I have a very special problem, concerning memory-accumulation (until collapse) while calling an OpenGL-controled dialog-window.
My program calculates the result of a packing problem and shows the result then (several packs) in 3D in a dialog window.
The result-graph in this dialog window is realized as a picture-control-area, that is controled by an OpenGL-class.
On the left and the right side of the picture-control, there are furthermore some other Non-OpenGL-controls, like editfields, buttons, etc.

The OpenGL-Class is embedded in the dialog-window-control-class as follows:


GetDlgItem(IDC_PICTUREGRAPH)->GetWindowRect(&rect);
ScreenToClient(rect);
m_oglWindow.oglCreate(rect, this);
m_oglWindow.m_unpTimer = m_oglWindow.SetTimer(1, 1, 0);


Almost everything works fine.
The result-dialog-window (with the OpenGL-managed 3D-result-graph = picture-control-area) can be called from the main menu of the program, whenever the user want.

The problem is, that each time when the result-dialog-window is called again from the main menu, after it was called and closed already before, the required memory of the process of my program, how it is shown in the windows task-manager, increases, about 3 MB with each call and close (effect of memory-waste-accumulation). The whole memory-requirement of my software starts for example with 8 MB, after 10 calls of the result-window, it is at 33 MB. So if the user uses the program long enough, it will collapse.

The cause of that effect is definitely the OpenGL-part. If I enclose this part as a comment (for a test), so that the result-dialog-window shows a blank picture-control-area, but the other controls (Editfields, buttons, etc.) are still active, the memory-accumulation-problem does no longer exist.

So what's the mistake ? What did I do wrong in my OpenGL-Code ? It is a total normal code, where I took the main part out of a published expert-example in the Web.
This is a tricky problem I guess, but my developed software can not be delivered to the customer, until this one is not solved. So please help me. All my own solve-attempts were not successful.

yooyo
05-02-2010, 12:27 AM
Did you released gl context and dc when on dialog close?

klickediklick
05-02-2010, 08:11 AM
It's funny. I already noticed on my own yesterday evening, shortly after I posted this thread, that I had forgotton to release the gl context.

The destructor of the OpenGL-Control-Class looks now like this:



OpenGLControl::~OpenGLControl ()
{
glDeleteLists(mglfont, 91);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hrc);
ReleaseDC(CDC::FromHandle (hdc));
}


But: Now I have no more 3 MB memory-leak per result-window-call, but still about 200 kb !
If I cancel the wglMakeCurrent and ReleaseDC-command from the destructor, there are still 200 kb, if I cancel also the wglDeleteContext-command, I have again the 3 MB.
I watched the code, but there is nothing I can find, that causes the additional memory (the 200 kb).
So the best would be, I post the code here, so that any expert will see hopefully more than I can see there inside:



void OpenGLControl::OnPaint ()
{
ValidateRect(NULL);
} // OnPaint


void OpenGLControl::OnSize (UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);

if (0 >= cx || 0 >= cy || nType == SIZE_MINIMIZED)
{
return;
}

glViewport(0, 0, cx, cy);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glFrustum(-frustumPlanes, frustumPlanes, -frustumPlanes, frustumPlanes, 10.0, frustumFar);
glMatrixMode(GL_MODELVIEW);
} // OnSize


int OpenGLControl::OnCreate (LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
{
return -1;
}
oglInitialize();

return 0;
} // OnCreate


void OpenGLControl::OnDraw (CDC *pDC)
{
glLoadIdentity();

glTranslated(drawBase1, 0.0, mfZoom);
glTranslated(drawBase2, heightDiff, 0.0);
glRotated(mfRotX, 1.0, 0.0, 0.0);
glRotated(mfRotY, 0.0, 1.0, 0.0);
} // OnDraw


void OpenGLControl::OnMouseMove (UINT nFlags, CPoint point)
{
int diffX = (int)(point.x - mfLastX);
int diffY = (int)(point.y - mfLastY);
mfLastX = (double)point.x;
mfLastY = (double)point.y;

if (nFlags & MK_LBUTTON)
{
mfRotX += (double)0.5 * diffY;

if ((mfRotX > 360.0) || (mfRotX < -360.0))
{
mfRotX = 0.0;
}
mfRotY += (double)0.5 * diffX;
if ((mfRotY > 360.0) || (mfRotY < -360.0))
{
mfRotY = 0.0;
}
OnDraw(NULL);
} // if

startflag = FALSE;
CWnd::OnMouseMove(nFlags, point);
} // OnMouseMove


void OpenGLControl::oglCreate (CRect rect, CWnd *parent)
{
CString className = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, (HBRUSH)GetStockObject(BLACK_BRUSH), NULL);

CreateEx(0, className, "OpenGL", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, rect, parent, 0);

hWnd = parent;
} // oglCreate


void OpenGLControl::DisplayText (CString str)
{
glPushAttrib(GL_LIST_BIT);
glListBase(mglfont - 32);
glCallLists(str.GetLength(), GL_UNSIGNED_BYTE, str);
glPopAttrib();
} // DisplayText


void OpenGLControl::oglInitialize ()
{
static PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
32,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
16,
0, 0, 0, 0, 0, 0, 0,
};

hdc = GetDC()->m_hDC;
mnPixelFormat = ChoosePixelFormat(hdc, &amp;pfd);
SetPixelFormat(hdc, mnPixelFormat, &amp;pfd);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc, hrc);
glClearColor(1.0, 1.0, 1.0, 1.0);
glClearDepth(1.0);
glFrontFace(GL_CCW);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);

HFONT hFont;
HFONT oldFont;

mglfont = glGenLists(91); // Generate the list for the font
hFont = ::CreateFont(
18, // Our desired HEIGHT of the font
0, // The WIDTH (If we leave this zero it will pick the best width depending on the height)
0, // The angle of escapement
0, // The angle of orientation
FW_BOLD, // The font's weight (We want it bold)
FALSE, // Italic - We don't want italic
FALSE, // Underline - We don't want it underlined
FALSE, // Strikeout - We don't want it strikethrough
ANSI_CHARSET, // This is the type of character set
OUT_DEFAULT_PRECIS, // The Output Precision
CLIP_DEFAULT_PRECIS, // The Clipping Precision
DEFAULT_QUALITY, // The quality of the font - We want anitaliased fonts
FF_DONTCARE|DEFAULT_PITCH, // The family and pitch of the font. We don't care.
"Arial"); // The font name (Like "Arial", "Courier", etc...)

oldFont = (HFONT)SelectObject(hdc, hFont);
wglUseFontBitmaps(hdc, 32, 91, mglfont);
SelectObject(hdc, oldFont);
DeleteObject(hFont);

glNewList( (GLint) PACKSTUECK, GL_COMPILE);
glBegin(GL_QUADS);

// Grundfläche
glVertex3d(0, 0, 0);
glVertex3d(0, 1.0, 0);
glVertex3d(1.0, 1.0, 0);
glVertex3d(1.0, 0, 0);

// Deckel
glVertex3d(0, 0, 1.0);
glVertex3d(0, 1.0, 1.0);
glVertex3d(1.0, 1.0, 1.0);
glVertex3d(1.0, 0, 1.0);

// Mantel
glVertex3d(0, 0, 0);
glVertex3d(1.0, 0, 0);
glVertex3d(1.0, 0, 1.0);
glVertex3d(0, 0, 1.0);

glVertex3d(0, 0, 0);
glVertex3d(0, 1.0, 0);
glVertex3d(0, 1.0, 1.0);
glVertex3d(0, 0, 1.0);

glVertex3d(0, 1.0, 0);
glVertex3d(0, 1.0, 1.0);
glVertex3d(1.0, 1.0, 1.0);
glVertex3d(1.0, 1.0, 0);

glVertex3d(1.0, 1.0, 0);
glVertex3d(1.0, 1.0, 1.0);
glVertex3d(1.0, 0, 1.0);
glVertex3d(1.0, 0, 0);
glEnd();
glEndList();

OnDraw(NULL);
} // oglInitialize


void OpenGLControl::OnTimer(UINT nIDEvent)
{
switch (nIDEvent)
{
case 1:
{
// Clear color and depth buffer bits
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Draw OpenGL scene
oglDrawScene();
// Swap buffers
SwapBuffers(hdc);
break;
}
default:
break;
}
CWnd::OnTimer(nIDEvent);
}